summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--MANIFEST.in2
-rw-r--r--doc/source/_theme/layout.html83
-rw-r--r--doc/source/_theme/theme.conf4
-rw-r--r--doc/source/architecture.rst2
-rw-r--r--doc/source/conf.py20
-rw-r--r--doc/source/configuration.rst91
-rw-r--r--doc/source/configuringservices.rst2
-rw-r--r--doc/source/man/keystone-all.rst2
-rw-r--r--doc/source/man/keystone-manage.rst2
-rw-r--r--etc/keystone.conf.sample46
-rw-r--r--etc/policy.json2
-rw-r--r--examples/pki/certs/cacert.pem25
-rw-r--r--examples/pki/certs/middleware.pem65
-rw-r--r--examples/pki/certs/signing_cert.pem25
-rw-r--r--examples/pki/certs/ssl_cert.pem25
-rw-r--r--examples/pki/cms/auth_token_revoked.pem14
-rw-r--r--examples/pki/cms/auth_token_scoped.pem13
-rw-r--r--examples/pki/cms/auth_token_unscoped.pem14
-rw-r--r--examples/pki/cms/revocation_list.pem13
-rw-r--r--examples/pki/private/cakey.pem40
-rw-r--r--examples/pki/private/signing_key.pem40
-rw-r--r--examples/pki/private/ssl_key.pem40
-rw-r--r--keystone/assignment/__init__.py18
-rw-r--r--keystone/assignment/backends/__init__.py (renamed from doc/source/_templates/.placeholder)0
-rw-r--r--keystone/assignment/backends/kvs.py499
-rw-r--r--keystone/assignment/backends/ldap.py543
-rw-r--r--keystone/assignment/backends/sql.py751
-rw-r--r--keystone/assignment/core.py548
-rw-r--r--keystone/auth/controllers.py115
-rw-r--r--keystone/auth/plugins/external.py87
-rw-r--r--keystone/auth/plugins/password.py12
-rw-r--r--keystone/auth/plugins/token.py5
-rw-r--r--keystone/auth/token_factory.py368
-rw-r--r--keystone/cli.py4
-rw-r--r--keystone/common/config.py46
-rw-r--r--keystone/common/controller.py14
-rw-r--r--keystone/common/dependency.py43
-rw-r--r--keystone/common/extension.py47
-rw-r--r--keystone/common/kvs.py2
-rw-r--r--keystone/common/logging.py4
-rw-r--r--keystone/common/openssl.py1
-rw-r--r--keystone/common/serializer.py3
-rw-r--r--keystone/common/sql/core.py65
-rw-r--r--keystone/common/sql/legacy.py14
-rw-r--r--keystone/common/sql/migrate_repo/versions/001_add_initial_tables.py56
-rw-r--r--keystone/common/sql/migrate_repo/versions/011_endpoints_v3.py20
-rw-r--r--keystone/common/sql/migrate_repo/versions/013_drop_legacy_endpoints.py20
-rw-r--r--keystone/common/sql/migrate_repo/versions/015_tenant_to_project.py63
-rw-r--r--keystone/common/sql/migrate_repo/versions/016_normalize_domain_ids.py4
-rw-r--r--keystone/common/sql/migrate_repo/versions/020_migrate_metadata_table_roles.py4
-rw-r--r--keystone/common/sql/migrate_repo/versions/027_set_engine_mysql_innodb.py143
-rw-r--r--keystone/common/sql/migrate_repo/versions/028_fixup_group_metadata.py190
-rw-r--r--keystone/common/sql/migrate_repo/versions/029_update_assignment_metadata.py102
-rw-r--r--keystone/common/sql/migrate_repo/versions/030_drop_credential_constraint_sqlite.py119
-rw-r--r--keystone/common/sql/migration_helpers.py37
-rw-r--r--keystone/common/sql/nova.py21
-rw-r--r--keystone/common/sql/util.py42
-rw-r--r--keystone/common/wsgi.py95
-rw-r--r--keystone/contrib/admin_crud/core.py21
-rw-r--r--keystone/contrib/ec2/core.py59
-rw-r--r--keystone/contrib/s3/core.py18
-rw-r--r--keystone/contrib/stats/core.py18
-rw-r--r--keystone/contrib/user_crud/core.py22
-rw-r--r--keystone/controllers.py40
-rw-r--r--keystone/exception.py128
-rw-r--r--keystone/identity/backends/kvs.py430
-rw-r--r--keystone/identity/backends/ldap.py568
-rw-r--r--keystone/identity/backends/pam.py16
-rw-r--r--keystone/identity/backends/sql.py632
-rw-r--r--keystone/identity/controllers.py355
-rw-r--r--keystone/identity/core.py382
-rw-r--r--keystone/identity/routers.py46
-rw-r--r--keystone/locale/bg_BG/LC_MESSAGES/keystone.po436
-rw-r--r--keystone/locale/bs/LC_MESSAGES/keystone.po848
-rw-r--r--keystone/locale/ca/LC_MESSAGES/keystone.po438
-rw-r--r--keystone/locale/cs/LC_MESSAGES/keystone.po436
-rw-r--r--keystone/locale/da/LC_MESSAGES/keystone.po436
-rw-r--r--keystone/locale/de/LC_MESSAGES/keystone.po452
-rw-r--r--keystone/locale/en_AU/LC_MESSAGES/keystone.po847
-rw-r--r--keystone/locale/en_GB/LC_MESSAGES/keystone.po847
-rw-r--r--keystone/locale/en_US/LC_MESSAGES/keystone.po847
-rw-r--r--keystone/locale/es/LC_MESSAGES/keystone.po453
-rw-r--r--keystone/locale/fi_FI/LC_MESSAGES/keystone.po436
-rw-r--r--keystone/locale/fr/LC_MESSAGES/keystone.po436
-rw-r--r--keystone/locale/hr/LC_MESSAGES/keystone.po848
-rw-r--r--keystone/locale/hu/LC_MESSAGES/keystone.po438
-rw-r--r--keystone/locale/id/LC_MESSAGES/keystone.po847
-rw-r--r--keystone/locale/it/LC_MESSAGES/keystone.po453
-rw-r--r--keystone/locale/it_IT/LC_MESSAGES/keystone.po847
-rw-r--r--keystone/locale/ja/LC_MESSAGES/keystone.po438
-rw-r--r--keystone/locale/ka_GE/LC_MESSAGES/keystone.po438
-rw-r--r--keystone/locale/keystone.pot429
-rw-r--r--keystone/locale/ko/LC_MESSAGES/keystone.po847
-rw-r--r--keystone/locale/ko_KR/LC_MESSAGES/keystone.po436
-rw-r--r--keystone/locale/ms/LC_MESSAGES/keystone.po847
-rw-r--r--keystone/locale/nb/LC_MESSAGES/keystone.po847
-rw-r--r--keystone/locale/nl_NL/LC_MESSAGES/keystone.po847
-rw-r--r--keystone/locale/pl_PL/LC_MESSAGES/keystone.po857
-rw-r--r--keystone/locale/pt/LC_MESSAGES/keystone.po847
-rw-r--r--keystone/locale/pt_BR/LC_MESSAGES/keystone.po436
-rw-r--r--keystone/locale/ro/LC_MESSAGES/keystone.po436
-rw-r--r--keystone/locale/ru/LC_MESSAGES/keystone.po436
-rw-r--r--keystone/locale/ru_RU/LC_MESSAGES/keystone.po848
-rw-r--r--keystone/locale/sl_SI/LC_MESSAGES/keystone.po857
-rw-r--r--keystone/locale/sw_KE/LC_MESSAGES/keystone.po847
-rw-r--r--keystone/locale/tl/LC_MESSAGES/keystone.po847
-rw-r--r--keystone/locale/tr_TR/LC_MESSAGES/keystone.po847
-rw-r--r--keystone/locale/uk/LC_MESSAGES/keystone.po848
-rw-r--r--keystone/locale/vi_VN/LC_MESSAGES/keystone.po436
-rw-r--r--keystone/locale/zh_CN/LC_MESSAGES/keystone.po450
-rw-r--r--keystone/locale/zh_HK/LC_MESSAGES/keystone.po847
-rw-r--r--keystone/locale/zh_TW/LC_MESSAGES/keystone.po450
-rw-r--r--keystone/openstack/common/crypto/__init__.py0
-rw-r--r--keystone/openstack/common/crypto/utils.py179
-rw-r--r--keystone/service.py16
-rw-r--r--keystone/test.py72
-rw-r--r--keystone/token/__init__.py1
-rw-r--r--keystone/token/backends/kvs.py17
-rw-r--r--keystone/token/backends/memcache.py12
-rw-r--r--keystone/token/backends/sql.py6
-rw-r--r--keystone/token/controllers.py341
-rw-r--r--keystone/token/core.py37
-rw-r--r--keystone/token/provider.py177
-rw-r--r--keystone/token/providers/__init__.py0
-rw-r--r--keystone/token/providers/pki.py44
-rw-r--r--keystone/token/providers/uuid.py577
-rw-r--r--keystone/trust/controllers.py18
-rw-r--r--openstack-common.conf1
-rw-r--r--requirements.txt2
-rw-r--r--setup.cfg1
-rw-r--r--test-requirements.txt30
-rw-r--r--tests/_ldap_livetest.py6
-rw-r--r--tests/_sql_livetest.py8
-rw-r--r--tests/auth_plugin_external_disabled.conf2
-rw-r--r--tests/auth_plugin_external_domain.conf3
-rw-r--r--tests/backend_db2.conf4
-rw-r--r--tests/backend_ldap_sql.conf36
-rw-r--r--tests/backend_liveldap.conf2
-rw-r--r--tests/backend_sql_disk.conf2
-rw-r--r--tests/backend_tls_liveldap.conf2
-rw-r--r--tests/default_fixtures.py22
-rw-r--r--tests/test_auth.py72
-rw-r--r--tests/test_auth_plugin.conf2
-rw-r--r--tests/test_auth_plugin.py6
-rw-r--r--tests/test_backend.py467
-rw-r--r--tests/test_backend_kvs.py22
-rw-r--r--tests/test_backend_ldap.py546
-rw-r--r--tests/test_backend_memcache.py2
-rw-r--r--tests/test_backend_pam.py8
-rw-r--r--tests/test_backend_sql.py144
-rw-r--r--tests/test_cert_setup.py1
-rw-r--r--tests/test_content_types.py61
-rw-r--r--tests/test_drivers.py5
-rw-r--r--tests/test_exception.py48
-rw-r--r--tests/test_import_legacy.py13
-rw-r--r--tests/test_injection.py44
-rw-r--r--tests/test_keystoneclient.py62
-rw-r--r--tests/test_keystoneclient_sql.py4
-rw-r--r--tests/test_middleware.py2
-rw-r--r--tests/test_migrate_nova_auth.py157
-rw-r--r--tests/test_no_admin_token_auth.py47
-rw-r--r--tests/test_pki_token_provider.conf2
-rw-r--r--tests/test_sql_core.py142
-rw-r--r--tests/test_sql_upgrade.py424
-rw-r--r--tests/test_token_bind.py182
-rw-r--r--tests/test_token_provider.py439
-rw-r--r--tests/test_uuid_token_provider.conf2
-rw-r--r--tests/test_v3.py127
-rw-r--r--tests/test_v3_auth.py519
-rw-r--r--tests/test_v3_identity.py940
-rw-r--r--tests/test_versions.py1
-rw-r--r--tests/test_wsgi.py30
-rw-r--r--tests/tmp/.gitkeep0
-rw-r--r--tools/install_venv_common.py42
-rw-r--r--tox.ini2
176 files changed, 33791 insertions, 5569 deletions
diff --git a/.gitignore b/.gitignore
index 16195c18..d4915b0b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
*.pyc
*.swp
+*.egg/
vendor
.ksl-venv
.venv
@@ -13,7 +14,6 @@ cover/*
covhtml
pep8.txt
nosetests.xml
-*.db
doc/build
.DS_Store
doc/source/modules.rst
@@ -24,6 +24,6 @@ build/
dist/
etc/keystone.conf
etc/logging.conf
-tests/test.db.pristine
+tests/tmp/
.project
.pydevproject
diff --git a/MANIFEST.in b/MANIFEST.in
index 93b762f7..2373ea28 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -20,4 +20,4 @@ graft tests
graft tools
graft examples
recursive-include keystone *.json *.xml *.cfg *.pem README *.po *.pot *.sql
-global-exclude *.pyc *.sdx *.log *.db *.swp
+global-exclude *.pyc *.sdx *.log *.db *.swp tests/tmp/*
diff --git a/doc/source/_theme/layout.html b/doc/source/_theme/layout.html
deleted file mode 100644
index 750b7822..00000000
--- a/doc/source/_theme/layout.html
+++ /dev/null
@@ -1,83 +0,0 @@
-{% extends "basic/layout.html" %}
-{% set css_files = css_files + ['_static/tweaks.css'] %}
-{% set script_files = script_files + ['_static/jquery.tweet.js'] %}
-
-{%- macro sidebar() %}
- {%- if not embedded %}{% if not theme_nosidebar|tobool %}
- <div class="sphinxsidebar">
- <div class="sphinxsidebarwrapper">
- {%- block sidebarlogo %}
- {%- if logo %}
- <p class="logo"><a href="{{ pathto(master_doc) }}">
- <img class="logo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/>
- </a></p>
- {%- endif %}
- {%- endblock %}
- {%- block sidebartoc %}
- {%- if display_toc %}
- <h3><a href="{{ pathto(master_doc) }}">{{ _('Table Of Contents') }}</a></h3>
- {{ toc }}
- {%- endif %}
- {%- endblock %}
- {%- block sidebarrel %}
- {%- if prev %}
- <h4>{{ _('Previous topic') }}</h4>
- <p class="topless"><a href="{{ prev.link|e }}"
- title="{{ _('previous chapter') }}">{{ prev.title }}</a></p>
- {%- endif %}
- {%- if next %}
- <h4>{{ _('Next topic') }}</h4>
- <p class="topless"><a href="{{ next.link|e }}"
- title="{{ _('next chapter') }}">{{ next.title }}</a></p>
- {%- endif %}
- {%- endblock %}
- {%- block sidebarsourcelink %}
- {%- if show_source and has_source and sourcename %}
- <h3>{{ _('This Page') }}</h3>
- <ul class="this-page-menu">
- <li><a href="{{ pathto('_sources/' + sourcename, true)|e }}"
- rel="nofollow">{{ _('Show Source') }}</a></li>
- </ul>
- {%- endif %}
- {%- endblock %}
- {%- if customsidebar %}
- {% include customsidebar %}
- {%- endif %}
- {%- block sidebarsearch %}
- {%- if pagename != "search" %}
- <div id="searchbox" style="display: none">
- <h3>{{ _('Quick search') }}</h3>
- <form class="search" action="{{ pathto('search') }}" method="get">
- <input type="text" name="q" size="18" />
- <input type="submit" value="{{ _('Go') }}" />
- <input type="hidden" name="check_keywords" value="yes" />
- <input type="hidden" name="area" value="default" />
- </form>
- <p class="searchtip" style="font-size: 90%">
- {{ _('Enter search terms or a module, class or function name.') }}
- </p>
- </div>
- <script type="text/javascript">$('#searchbox').show(0);</script>
- {%- endif %}
- {%- endblock %}
- </div>
- </div>
- {%- endif %}{% endif %}
-{%- endmacro %}
-
-{% block relbar1 %}{% endblock relbar1 %}
-
-{% block header %}
- <div id="header">
- <h1 id="logo"><a href="http://www.openstack.org/">OpenStack</a></h1>
- <ul id="navigation">
- <li><a href="http://www.openstack.org/" title="Go to the Home page" class="link">Home</a></li>
- <li><a href="http://www.openstack.org/projects/" title="Go to the OpenStack Projects page">Projects</a></li>
- <li><a href="http://www.openstack.org/user-stories/" title="Go to the User Stories page" class="link">User Stories</a></li>
- <li><a href="http://www.openstack.org/community/" title="Go to the Community page" class="link">Community</a></li>
- <li><a href="http://www.openstack.org/blog/" title="Go to the OpenStack Blog">Blog</a></li>
- <li><a href="http://wiki.openstack.org/" title="Go to the OpenStack Wiki">Wiki</a></li>
- <li><a href="http://docs.openstack.org/" title="Go to OpenStack Documentation" class="current">Documentation</a></li>
- </ul>
- </div>
-{% endblock %} \ No newline at end of file
diff --git a/doc/source/_theme/theme.conf b/doc/source/_theme/theme.conf
deleted file mode 100644
index 1cc40044..00000000
--- a/doc/source/_theme/theme.conf
+++ /dev/null
@@ -1,4 +0,0 @@
-[theme]
-inherit = basic
-stylesheet = nature.css
-pygments_style = tango
diff --git a/doc/source/architecture.rst b/doc/source/architecture.rst
index 7ffaea4b..c3ddf0ce 100644
--- a/doc/source/architecture.rst
+++ b/doc/source/architecture.rst
@@ -178,7 +178,7 @@ interpolation)::
LDAP Backend
------------
-The LDAP backend stored Users and Tenents in separate Subtrees. Roles are recorded
+The LDAP backend stored Users and Tenants in separate Subtrees. Roles are recorded
as entries under the Tenants.
diff --git a/doc/source/conf.py b/doc/source/conf.py
index 293edf44..cd585d68 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -28,21 +28,19 @@ sys.path.insert(0, os.path.abspath('../..'))
# 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.intersphinx',
-# 'sphinx.ext.todo', 'sphinx.ext.coverage']
extensions = ['sphinx.ext.autodoc',
'sphinx.ext.todo',
- # 'sphinx.ect.intersphinx',
- 'sphinx.ext.coverage']
+ 'sphinx.ext.coverage',
+ 'oslo.sphinx',
+ ]
todo_include_todos = True
# Add any paths that contain templates here, relative to this directory.
-templates_path = []
-if os.getenv('HUDSON_PUBLISH_DOCS'):
- templates_path = ['_ga', '_templates']
-else:
- templates_path = ['_templates']
+# if os.getenv('HUDSON_PUBLISH_DOCS'):
+# templates_path = ['_ga', '_templates']
+# else:
+# templates_path = ['_templates']
# The suffix of source filenames.
source_suffix = '.rst'
@@ -109,8 +107,8 @@ man_pages = [
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
-html_theme_path = ["."]
-html_theme = '_theme'
+# html_theme_path = ["."]
+# html_theme = '_theme'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
diff --git a/doc/source/configuration.rst b/doc/source/configuration.rst
index 03fa1d63..1c339490 100644
--- a/doc/source/configuration.rst
+++ b/doc/source/configuration.rst
@@ -74,11 +74,12 @@ following sections:
* ``[s3]`` - Amazon S3 authentication driver configuration.
* ``[identity]`` - identity system driver configuration
* ``[catalog]`` - service catalog driver configuration
-* ``[token]`` - token driver configuration
+* ``[token]`` - token driver & token provider configuration
* ``[policy]`` - policy system driver configuration for RBAC
* ``[signing]`` - cryptographic signatures for PKI based tokens
* ``[ssl]`` - SSL configuration
* ``[auth]`` - Authentication plugin configuration
+* ``[os_inherit]`` - Inherited Role Assignment extension
* ``[paste_deploy]`` - Pointer to the PasteDeploy configuration file
The Keystone primary configuration file is expected to be named ``keystone.conf``.
@@ -106,7 +107,10 @@ file. It is up to the plugin to register its own configuration options.
* ``methods`` - comma-delimited list of authentication plugin names
* ``<plugin name>`` - specify the class which handles to authentication method, in the same manner as one would specify a backend driver.
-Keystone provides two authentication methods by default. ``password`` handles password authentication and ``token`` handles token authentication.
+Keystone provides three authentication methods by default. ``password`` handles password
+authentication and ``token`` handles token authentication. ``external`` is used in conjunction
+with authentication performed by a container web server that sets the ``REMOTE_USER``
+environment variable.
How to Implement an Authentication Plugin
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -148,6 +152,32 @@ invoked, all plugins must succeed in order to for the entire
authentication to be successful. Furthermore, all the plugins invoked must
agree on the ``user_id`` in the ``auth_context``.
+The ``REMOTE_USER`` environment variable is only set from a containing webserver. However,
+to ensure that a user must go through other authentication mechanisms, even if this variable
+is set, remove ``external`` from the list of plugins specified in ``methods``. This effectively
+disables external authentication.
+
+
+Token Provider
+--------------
+
+Keystone supports customizable token provider and it is specified in the
+``[token]`` section of the configuration file. Keystone provides both UUID and
+PKI token providers, with PKI token provider enabled as default. However, users
+may register their own token provider by configuring the following property.
+
+* ``provider`` - token provider driver. Defaults to
+ ``keystone.token.providers.pki.Provider``
+
+Note that ``token_format`` in the ``[signing]`` section is deprecated but still
+being supported for backward compatibility. Therefore, if ``provider`` is set
+to ``keystone.token.providers.pki.Provider``, ``token_format`` must be ``PKI``.
+Conversely, if ``provider`` is ``keystone.token.providers.uuid.Provider``,
+``token_format`` must be ``UUID``.
+
+For a customized provider, ``token_format`` must not set to ``PKI`` or
+``UUID``.
+
Certificates for PKI
--------------------
@@ -163,7 +193,9 @@ private key should only be readable by the system user that will run Keystone.
The values that specify where to read the certificates are under the
``[signing]`` section of the configuration file. The configuration values are:
-* ``token_format`` - Determines the algorithm used to generate tokens. Can be either ``UUID`` or ``PKI``. Defaults to ``PKI``
+* ``token_format`` - Determines the algorithm used to generate tokens. Can be
+ either ``UUID`` or ``PKI``. Defaults to ``PKI``. This option must be used in
+ conjunction with ``provider`` configuration in the ``[token]`` section.
* ``certfile`` - Location of certificate used to verify tokens. Default is ``/etc/keystone/ssl/certs/signing_cert.pem``
* ``keyfile`` - Location of private key used to sign tokens. Default is ``/etc/keystone/ssl/private/signing_key.pem``
* ``ca_certs`` - Location of certificate for the authority that issued the above certificate. Default is ``/etc/keystone/ssl/certs/ca.pem``
@@ -460,7 +492,56 @@ Each user can then change their own password with a HTTP PATCH ::
-H "X_Auth_Token: <authtokenid>" -d '{"user": {"password": "ABCD", "original_password": "DCBA"}}'
In addition to changing their password all of the users current tokens will be
-deleted (if the backend used is kvs or sql)
+deleted (if the backend used is sql)
+
+
+Inherited Role Assignment Extension
+-----------------------------------
+
+Keystone provides an optional extension that adds the capability to assign roles to a domain that, rather than
+affect the domain itself, are instead inherited to all projects owned by theat domain. This extension is disabled by
+default, but can be enabled by including the following in ``keystone.conf``.
+
+ [os_inherit]
+ enabled = True
+
+
+Token Binding
+-------------
+
+Token binding refers to the practice of embedding information from external
+authentication providers (like a company's Kerberos server) inside the token
+such that a client may enforce that the token only be used in conjunction with
+that specified authentication. This is an additional security mechanism as it
+means that if a token is stolen it will not be usable without also providing the
+external authentication.
+
+To activate token binding you must specify the types of authentication that
+token binding should be used for in ``keystone.conf`` e.g.::
+
+ [token]
+ bind = kerberos
+
+Currently only ``kerberos`` is supported.
+
+To enforce checking of token binding the ``enforce_token_bind`` parameter
+should be set to one of the following modes:
+
+* ``disabled`` disable token bind checking
+* ``permissive`` enable bind checking, if a token is bound to a mechanism that
+ is unknown to the server then ignore it. This is the default.
+* ``strict`` enable bind checking, if a token is bound to a mechanism that is
+ unknown to the server then this token should be rejected.
+* ``required`` enable bind checking and require that at least 1 bind mechanism
+ is used for tokens.
+* named enable bind checking and require that the specified authentication
+ mechanism is used. e.g.::
+
+ [token]
+ enforce_token_bind = kerberos
+
+ *Do not* set ``enforce_token_bind = named`` as there is not an authentication
+ mechanism called ``named``.
Sample Configuration Files
@@ -1079,7 +1160,7 @@ if the backend is providing too much output, in such case the configuration
will look like::
[ldap]
- user_filter = (memberof=CN=openstack-users,OU=workgroups,DC=openstack,DC=com)
+ user_filter = (memberof=CN=openstack-users,OU=workgroups,DC=openstack,DC=org)
tenant_filter =
role_filter =
diff --git a/doc/source/configuringservices.rst b/doc/source/configuringservices.rst
index 8ea7ad90..645ab5da 100644
--- a/doc/source/configuringservices.rst
+++ b/doc/source/configuringservices.rst
@@ -93,7 +93,7 @@ Create a tenant for the services, typically named 'service' (however, the name c
This returns a UUID of the tenant - keep that, you'll need it when creating
the users and specifying the roles.
-Create service users for nova, glance, swift, and quantum (or whatever
+Create service users for nova, glance, swift, and neutron (or whatever
subset is relevant to your deployment)::
keystone user-create --name=nova \
diff --git a/doc/source/man/keystone-all.rst b/doc/source/man/keystone-all.rst
index 9b0859d9..76d5ab1f 100644
--- a/doc/source/man/keystone-all.rst
+++ b/doc/source/man/keystone-all.rst
@@ -6,7 +6,7 @@ keystone-all
Keystone Startup Command
------------------------
-:Author: openstack@lists.launchpad.net
+:Author: openstack@lists.openstack.org
:Date: 2010-11-16
:Copyright: OpenStack LLC
:Version: 2012.1
diff --git a/doc/source/man/keystone-manage.rst b/doc/source/man/keystone-manage.rst
index 84a3ec9f..1da4b40a 100644
--- a/doc/source/man/keystone-manage.rst
+++ b/doc/source/man/keystone-manage.rst
@@ -6,7 +6,7 @@ keystone-manage
Keystone Management Utility
---------------------------
-:Author: openstack@lists.launchpad.net
+:Author: openstack@lists.openstack.org
:Date: 2010-11-16
:Copyright: OpenStack LLC
:Version: 2012.1
diff --git a/etc/keystone.conf.sample b/etc/keystone.conf.sample
index 9a36316d..a49a9a5e 100644
--- a/etc/keystone.conf.sample
+++ b/etc/keystone.conf.sample
@@ -109,6 +109,11 @@
# delegation and impersonation features can be optionally disabled
# enabled = True
+[os_inherit]
+# role-assignment inheritance to projects from owning domain can be
+# optionally enabled
+# enabled = False
+
[catalog]
# dynamic, sql-based backend (supports API/CLI-based management commands)
# driver = keystone.catalog.backends.sql.Catalog
@@ -119,23 +124,40 @@
# template_file = default_catalog.templates
[token]
+# Provides token persistence.
# driver = keystone.token.backends.sql.Token
+# Controls the token construction, validation, and revocation operations.
+# Core providers are keystone.token.providers.[pki|uuid].Provider
+# provider =
+
# Amount of time a token should remain valid (in seconds)
# expiration = 86400
+# External auth mechanisms that should add bind information to token.
+# eg kerberos, x509
+# bind =
+
+# Enforcement policy on tokens presented to keystone with bind information.
+# One of disabled, permissive, strict, required or a specifically required bind
+# mode e.g. kerberos or x509 to require binding to that authentication.
+# enforce_token_bind = permissive
+
[policy]
# driver = keystone.policy.backends.sql.Policy
[ec2]
# driver = keystone.contrib.ec2.backends.kvs.Ec2
+[assignment]
+# driver =
+
[ssl]
#enable = True
-#certfile = /etc/keystone/ssl/certs/keystone.pem
-#keyfile = /etc/keystone/ssl/private/keystonekey.pem
-#ca_certs = /etc/keystone/ssl/certs/ca.pem
-#ca_key = /etc/keystone/ssl/certs/cakey.pem
+#certfile = /etc/keystone/pki/certs/ssl_cert.pem
+#keyfile = /etc/keystone/pki/private/ssl_key.pem
+#ca_certs = /etc/keystone/pki/certs/cacert.pem
+#ca_key = /etc/keystone/pki/private/cakey.pem
#key_size = 1024
#valid_days = 3650
#ca_password = None
@@ -143,11 +165,14 @@
#cert_subject = /C=US/ST=Unset/L=Unset/O=Unset/CN=localhost
[signing]
-#token_format = PKI
-#certfile = /etc/keystone/ssl/certs/signing_cert.pem
-#keyfile = /etc/keystone/ssl/private/signing_key.pem
-#ca_certs = /etc/keystone/ssl/certs/ca.pem
-#ca_key = /etc/keystone/ssl/certs/cakey.pem
+# Deprecated in favor of provider in the [token] section
+# Allowed values are PKI or UUID
+#token_format =
+
+#certfile = /etc/keystone/pki/certs/signing_cert.pem
+#keyfile = /etc/keystone/pki/private/signing_key.pem
+#ca_certs = /etc/keystone/pki/certs/cacert.pem
+#ca_key = /etc/keystone/pki/private/cakey.pem
#key_size = 2048
#valid_days = 3650
#ca_password = None
@@ -253,7 +278,8 @@
# user_additional_attribute_mapping =
[auth]
-methods = password,token
+methods = external,password,token
+#external = keystone.auth.plugins.external.ExternalDefault
password = keystone.auth.plugins.password.Password
token = keystone.auth.plugins.token.Token
diff --git a/etc/policy.json b/etc/policy.json
index 4aad4e8c..2c82f994 100644
--- a/etc/policy.json
+++ b/etc/policy.json
@@ -66,6 +66,8 @@
"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"]],
diff --git a/examples/pki/certs/cacert.pem b/examples/pki/certs/cacert.pem
index a0d98c6e..2f31d126 100644
--- a/examples/pki/certs/cacert.pem
+++ b/examples/pki/certs/cacert.pem
@@ -1,18 +1,23 @@
-----BEGIN CERTIFICATE-----
-MIIC0TCCAjqgAwIBAgIJANsHKV73HYOwMA0GCSqGSIb3DQEBBQUAMIGeMQowCAYD
+MIID1jCCAr6gAwIBAgIJAKiIU3dYUGKeMA0GCSqGSIb3DQEBBQUAMIGeMQowCAYD
VQQFEwE1MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVN1bm55
dmFsZTESMBAGA1UEChMJT3BlblN0YWNrMREwDwYDVQQLEwhLZXlzdG9uZTElMCMG
CSqGSIb3DQEJARYWa2V5c3RvbmVAb3BlbnN0YWNrLm9yZzEUMBIGA1UEAxMLU2Vs
-ZiBTaWduZWQwIBcNMTIxMTA1MTgxODI0WhgPMjA3MTA0MzAxODE4MjRaMIGeMQow
+ZiBTaWduZWQwIBcNMTMwNzA5MTYyNTAwWhgPMjA3MjAxMDExNjI1MDBaMIGeMQow
CAYDVQQFEwE1MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVN1
bm55dmFsZTESMBAGA1UEChMJT3BlblN0YWNrMREwDwYDVQQLEwhLZXlzdG9uZTEl
MCMGCSqGSIb3DQEJARYWa2V5c3RvbmVAb3BlbnN0YWNrLm9yZzEUMBIGA1UEAxML
-U2VsZiBTaWduZWQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALzI17ExCaqd
-r7xY2Q5CBZ1bW1lsrXxS8eNJRdQtskDuQVAluY03/OGZd8HQYiiY/ci2tYy7BNIC
-bh5GaO95eqTDykJR3liOYE/tHbY6puQlj2ZivmhlSd2d5d7lF0/H28RQsLu9VktM
-uw6q9DpDm35jfrr8LgSeA3MdVqcS/4OhAgMBAAGjEzARMA8GA1UdEwEB/wQFMAMB
-Af8wDQYJKoZIhvcNAQEFBQADgYEAjSQND7i1dNZtLKpWgX+JqMr3BdVlM15mFeVr
-C26ZspZjZVY5okdozO9gU3xcwRe4Cg30sKFOe6EBQKpkTZucFOXwBtD3h6dWJrdD
-c+m/CL/rs0GatDavbaIT2vv405SQUQooCdVh72LYel+4/a6xmRd7fQx3iEXN9QYj
-vmHJUcA=
+U2VsZiBTaWduZWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCh1U+N
+3g2cjFi7GeVf21FIv8MDhughFCey9rysAuqFONSFYo2rectLgpDtVy4BFFUFlxmh
+8Ci9TEZ5LiA31tbc4584GxvlLt4dg8aFsUJRBKq0L9i7W5v9uFpHrY1Zr+P4vwG+
+v7IWOuzw19f517eGpp6LLcj2vrpN9Yb63rrydKOqr0KJodMd+vFKmi+euFcPqs6s
+w1OiC5DpJN479CGl2Fs1WzMoKDedRNiXG7ysrVrYQIkfMBABBPIwilq1xXZz9Ybo
+0PbNgOu6xpSsy9hq+IzxcwYsr5CwIcbqW6Ju+Ti2iBEaff20lW7dFzO4kwrcqOr9
+Jnn7qE8YfJo9Hyj3AgMBAAGjEzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcN
+AQEFBQADggEBAGWFTQTe2FwvwGWa/Bx3Ypc8pJ05ucmGDm8XZiUHj1mOvFHTcveL
+Iofb+vR2lynr+MwF9Dn1szGteVNn/QxrHJIoxsgf1n/9fdyYqjoKWXblNBMt5jhr
+IlMGdQMqHSDzlkZKbcXg5vzHnG5mrwh0rojcZItZznXTSo/XnujEtHwIvCo6rk9c
+tRRzpkcDkg+/SZf2izchsLoEQVsJsIZMnWl0hUGFHaDfx2JQn7bnAcC84wPVhRJ+
+Xa3kDok1r7Nd7Vr/Wf0hCNRxyv2dySD/bq5iCEl1HNik3KCq4eUicTtkGe5N+Was
+ucf1RhPD3oZbxlTX4QDN7grSCdrTESyuhfc=
-----END CERTIFICATE-----
diff --git a/examples/pki/certs/middleware.pem b/examples/pki/certs/middleware.pem
index 86095248..6546753e 100644
--- a/examples/pki/certs/middleware.pem
+++ b/examples/pki/certs/middleware.pem
@@ -1,33 +1,50 @@
-----BEGIN CERTIFICATE-----
-MIICoTCCAgoCARAwDQYJKoZIhvcNAQEFBQAwgZ4xCjAIBgNVBAUTATUxCzAJBgNV
+MIIDpjCCAo4CARAwDQYJKoZIhvcNAQEFBQAwgZ4xCjAIBgNVBAUTATUxCzAJBgNV
BAYTAlVTMQswCQYDVQQIEwJDQTESMBAGA1UEBxMJU3Vubnl2YWxlMRIwEAYDVQQK
EwlPcGVuU3RhY2sxETAPBgNVBAsTCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZr
ZXlzdG9uZUBvcGVuc3RhY2sub3JnMRQwEgYDVQQDEwtTZWxmIFNpZ25lZDAgFw0x
-MjExMDUxODE4MjRaGA8yMDcxMDQzMDE4MTgyNFowgZAxCzAJBgNVBAYTAlVTMQsw
+MzA3MDkxNjI1MDBaGA8yMDcyMDEwMTE2MjUwMFowgZAxCzAJBgNVBAYTAlVTMQsw
CQYDVQQIEwJDQTESMBAGA1UEBxMJU3Vubnl2YWxlMRIwEAYDVQQKEwlPcGVuU3Rh
Y2sxETAPBgNVBAsTCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZrZXlzdG9uZUBv
-cGVuc3RhY2sub3JnMRIwEAYDVQQDEwlsb2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEB
-BQADgY0AMIGJAoGBANRG3ZkIJ+NaY9smirkZ+Lzf1Ka18xOvc2kizemUMeAchs9h
-lP0Kpm8EBHal1vgzSuXncP8gyQ6nMZUw5NhFMZ1kLSfzoB/hCyTlIp/4VZbCAtn4
-3zlTUSgQQMH+6I4k4sZDOiIAE7yvzEMa71RkqBzduuFoeuhBm5oqmRa8kac5AgMB
-AAEwDQYJKoZIhvcNAQEFBQADgYEAJLnmyYiBDNdykLeh3+HXCOExUt49/OzomB6c
-6NWq3j7efYBfh6zCgyowx/v0hEVcxYBunTfXgOGunjx0u5X13PuLRO7Qxv6Crdy6
-st0mZ0itCsp58uGz5n+ZVhG//NiweTKw9M12Mejs0L/JGtf5gPBCFkVvrl8ffwRG
-060Ep/k=
+cGVuc3RhY2sub3JnMRIwEAYDVQQDEwlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQC5dpW18l3bs+Mcj/JdhaAa+qw1RJwShm06g+q38ZoC
+cCmRO3/XyHghgHWdVa+FKVm2ug923dE2PW4GSI1pZa3iqbT9Yj70nxN+0l94iym+
+v9/P7irolvo5OWBbBIJT1Ubjps5fJ//gz6BdmwS0FuOy2qfKPnPhyBDH2VawtOgY
+MLk+PSG3YQh7vM2YvDALPTPz/f4qPmhQpb69KBJQElFXPQ9Nu0ABCPWWC2tN87L5
+pakFw5zq46pttSJ7Izc8MXh3KQrh9FvjmiQuRnkMvQ/g887Sp6nEJ22ABPEFhuRr
+89aup6wRD2CkA/8L3zSB5BV7tTK4hQiq07cTnV9Dv6bfAgMBAAEwDQYJKoZIhvcN
+AQEFBQADggEBAIVz3ZwxSUF/y5ABmjnVIQaVVxH97bu07smFQUe0AB2I9R4xnBJ9
+jn93DpeixZvArCZuDuJEJvNER8S6L3r/OPMPrVzayxibXATaZRE8khMWEJpsnyeW
+8paA5NuZJwN2NjlPOmT47J1m7ZjLgkrVwjhwQZPMnh5kG9690TBJNhg9x3Z8f6p3
+iKj2AfZWGhp9Xr2xOZCpfvAZmyvKOMeuHVrRZ2VWGuzojQd7fjSEDw/+Tg8Gw1LV
+BQXjXiKQHsD1YID2a9Pe9yrBjO00ZMxMw8+wN9qrh+8vxfmwTO8tEkmcpvM4ivO3
+/oGGhQh6nSncERVI7rx+wBDnIHKBz6MU2Ow=
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
-MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBANRG3ZkIJ+NaY9sm
-irkZ+Lzf1Ka18xOvc2kizemUMeAchs9hlP0Kpm8EBHal1vgzSuXncP8gyQ6nMZUw
-5NhFMZ1kLSfzoB/hCyTlIp/4VZbCAtn43zlTUSgQQMH+6I4k4sZDOiIAE7yvzEMa
-71RkqBzduuFoeuhBm5oqmRa8kac5AgMBAAECgYBngOI94tcoKQO1cJaFaJ964Jyc
-aO1L9OmOIvVJ5gNnpiEpbwgpVY8PZGMUwwoNXV0wumfDTmYaafVoLD35IcvtcS3D
-Tmsm+zC3ZQYzbQrIkQrtXE+y4bMwtscOTd61YDFQE++0omg3qckVu8IYSdFtTb9D
-SjSsWMnYoDmGrBqCHQJBAP2jq2I5fMPSR3LY5FdejwhyUcqs6AKyJD0BDJzIhdV6
-d0InWWss/atR4sMnOX7WKIo1m4+X+0+T2F69kj9hge8CQQDWQKTvbvlDugiziwNc
-FRl+yC7YTJ34toRFI4xbszKL3vgk4KDgfSQeoPp9KeHXmjgTfXIOwSVI83QBoL1d
-LHFXAkEAglD9VVJEEDiSDSfy6hDjXGugKon8CqaMh+tqF4PPf4eUjqC5CJ/tFYDV
-CX+1wr01xw0UCAsGTDSiDstHwNjQcQJAAkF3+xVeBnqE8O77wBJwzEbrR1e3KhEx
-31B6f9SpKZPVZP4Ac5ydrrzfJkY0nIKBKKNfegxKijQV+pZop/x5zQJASGTmKcW2
-WKj4P8PiolVlWH2ZTARSschff5wDV6nBneb5zWNgpPORrSRPl9yrYrgqk4vvjLh5
-rUiR/G65ZjmbnA==
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC5dpW18l3bs+Mc
+j/JdhaAa+qw1RJwShm06g+q38ZoCcCmRO3/XyHghgHWdVa+FKVm2ug923dE2PW4G
+SI1pZa3iqbT9Yj70nxN+0l94iym+v9/P7irolvo5OWBbBIJT1Ubjps5fJ//gz6Bd
+mwS0FuOy2qfKPnPhyBDH2VawtOgYMLk+PSG3YQh7vM2YvDALPTPz/f4qPmhQpb69
+KBJQElFXPQ9Nu0ABCPWWC2tN87L5pakFw5zq46pttSJ7Izc8MXh3KQrh9FvjmiQu
+RnkMvQ/g887Sp6nEJ22ABPEFhuRr89aup6wRD2CkA/8L3zSB5BV7tTK4hQiq07cT
+nV9Dv6bfAgMBAAECggEBAIB1K5L/kZUITulMptGyKUgmkjq/D98g7u0Vy/CmTkcc
+Cx6F+LGsL9D8mfplDBKOpo4S530sfKk1+Uwu2ovDGqKhazQJ5ZMnz6gK7Ieg1ERD
+wDDURTIeyKf0HtJMGD0av2QU+GIeYXQEO446PhLCu+n42zkQ8tDS8xSJbCsu0odV
+ok6+i7nEg9sP4uDfAAtM8CUJbRpFTha+m2a7pOz3ylU7/ZV4FDIgJ+FEynaphXAo
+bZE4MX5I7A4DDBp7/9g9HsgefByY4xiABuk7Rsyztyf2TrJEtcsVhiV4sCIIHsow
+u60KGEcTQWj4npBIMgW1QUdrwmAAh/35gOjt9ZndgTkCgYEA2yT5DmihjVaNF65B
+8VtdFcpESr8rr6FBmJ7z31m7MufeV1Inc5GqCK9agRmpr5sTYcgFB9it2IhW2WsA
+xHv+7J04bd9DBtgTv58GWrISsCR/abMZnJrm+F5Rafk77jwjCx/SwFj79ybI83Ia
+VJYMd7jqkxc00+DZT/3QWZqRrlsCgYEA2KeBBqUVdCpwNiJpgFM18HWjJx36HRk7
+YoFapXot/6R6A/rYmS+/goBZt2CWqqGtnXqWEZvH+v4L+WlUmYQrWwtoxpdR1oXz
+EmlCxN7D9MbRVR7QVW24h5zdwPOlbCTGoKzowOs8UEjMfQ81zoMinLmcJgHQSyzs
+OawgSF+DmM0CgYBQz26EELNaMktvKxQoE3/c9CyAv8Q1TKqqxBq8BxPP7s7/tkzU
+AigIcdlW+Aapue7IxQCN5yocShJ0tE+hJPRZfpR7d7P4xx9pLxQhx766c4sEiEXu
+iPSZK/artHuUG1r01DRcN7QabJP3qeDpxjcswuTFfu49H5IjPD5jfGsyNwKBgFjh
+bvdQ5lo/xsUOnQV+HZTGTeaQT7l8TnZ85rkYRKKp0TysvgsqIYDiMuwd/fGGXnlK
+fyI+LG51pmftpD1OkZLKPXOrRHGjhjK5aCDn2rAimGI5P/KsDpXj7r1ntyeEdtAX
+32y1lIrDMtDjWomcFqkBJGQbPl540Xhfeub1+EDJAoGAUZGPT2itKnxEFsa1SKHW
+yLeEsag/a9imAVyizo1WJn2WJaUhi1aHK49w6JRowIAzXXb7zLQt7BL8v+ydPVw3
+eySpXGqFuN/Prm3So0SeWllWcPsKFAzjgE0CWjNuB0GlAZGOaJOcWUNoOZjX/SDC
+FpolIoaSad28tGc8tbEk3fU=
-----END PRIVATE KEY-----
diff --git a/examples/pki/certs/signing_cert.pem b/examples/pki/certs/signing_cert.pem
index a6656490..3129e508 100644
--- a/examples/pki/certs/signing_cert.pem
+++ b/examples/pki/certs/signing_cert.pem
@@ -1,17 +1,22 @@
-----BEGIN CERTIFICATE-----
-MIICoDCCAgkCAREwDQYJKoZIhvcNAQEFBQAwgZ4xCjAIBgNVBAUTATUxCzAJBgNV
+MIIDpTCCAo0CAREwDQYJKoZIhvcNAQEFBQAwgZ4xCjAIBgNVBAUTATUxCzAJBgNV
BAYTAlVTMQswCQYDVQQIEwJDQTESMBAGA1UEBxMJU3Vubnl2YWxlMRIwEAYDVQQK
EwlPcGVuU3RhY2sxETAPBgNVBAsTCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZr
ZXlzdG9uZUBvcGVuc3RhY2sub3JnMRQwEgYDVQQDEwtTZWxmIFNpZ25lZDAgFw0x
-MjExMDUxODE4MjRaGA8yMDcxMDQzMDE4MTgyNFowgY8xCzAJBgNVBAYTAlVTMQsw
+MzA3MDkxNjI1MDBaGA8yMDcyMDEwMTE2MjUwMFowgY8xCzAJBgNVBAYTAlVTMQsw
CQYDVQQIEwJDQTESMBAGA1UEBxMJU3Vubnl2YWxlMRIwEAYDVQQKEwlPcGVuU3Rh
Y2sxETAPBgNVBAsTCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZrZXlzdG9uZUBv
-cGVuc3RhY2sub3JnMREwDwYDVQQDEwhLZXlzdG9uZTCBnzANBgkqhkiG9w0BAQEF
-AAOBjQAwgYkCgYEA0GemENJ+fs5OaT8k4uA7ETRDA/oX/tUKCVAfxfYveHAdQqEK
-DcUbthdXTnhkBnv0OZIpxBPxwREZSZK2I/hekPrBILZ4USzozFCgudXA43QMkBlc
-uQ+VOI2/q5H4z2knxaexsBjPeIX7D9NowtTYFlOgSqCix8xWIcNW1x1En1cCAwEA
-ATANBgkqhkiG9w0BAQUFAAOBgQA/EpklfmPBW7rEoxvocRDk63gDvQ1HxhQItQDF
-9ALWdSwLtL8c3/TQzGgoKZ8+a+p7RnNEsmzNOWHTaWHL91GcRrAEhXwBtu4G/dLu
-sXguhHj9UfT+6ivFbvDF2JK9rPpKhSqTVWVnkY5JQKinDX1wFRHLQB/SVHysT+zt
-nkZ7wg==
+cGVuc3RhY2sub3JnMREwDwYDVQQDEwhLZXlzdG9uZTCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBAMTC6IdNd9Cg1DshcrT5gRVRF36nEmjSA9QWdik7B925
+PK70U4F6j4pz/5JL7plIo/8rJ4jJz9ccE7m0iA+IuABtEhEwXkG9rj47Oy0J4ZyD
+GSh2K1Bl78PA9zxXSzysUTSjBKdAh29dPYbJY7cgZJ0uC3AtfVceYiAOIi14SdFe
+Z0LZLDXBuLaqUmSMrmKwJ9wAMOCb/jbBP9/3Ycd0GYjlvrSBU4Bqb8/NHasyO4Dp
+PN68OAoyD5r5jUtV8QZN03UjIsoux8e0lrL6+MVtJo0OfWvlSrlzS5HKSryY+uqq
+QEuxtZKpJM2MV85ujvjc8eDSChh2shhDjBem3FIlHKUCAwEAATANBgkqhkiG9w0B
+AQUFAAOCAQEAed9fHgdJrk+gZcO5gsqq6uURfDOuYD66GsSdZw4BqHjYAcnyWq2d
+a+iw7Uxkqu7iLf2k4+Hu3xjDFrce479OwZkSnbXmqB7XspTGOuM8MgT7jB/ypKTO
+Z6qaZKSWK1Hta995hMrVVlhUNBLh0MPGqoVWYA4d7mblujgH9vp+4mpCciJagHks
+8K5FBmI+pobB+uFdSYDoRzX9LTpStspK4e3IoY8baILuGcdKimRNBv6ItG4hMrnt
+Ae1/nWMJyUu5rDTGf2V/vAaS0S/faJBwQSz1o38QHMTWHNspfwIdX3yMqI9u7/vY
+lz3rLy5WdBdUgZrZ3/VLmJTiJVZu5Owq4Q==
-----END CERTIFICATE-----
diff --git a/examples/pki/certs/ssl_cert.pem b/examples/pki/certs/ssl_cert.pem
index 4a415ebc..0b0877eb 100644
--- a/examples/pki/certs/ssl_cert.pem
+++ b/examples/pki/certs/ssl_cert.pem
@@ -1,17 +1,22 @@
-----BEGIN CERTIFICATE-----
-MIICoTCCAgoCARAwDQYJKoZIhvcNAQEFBQAwgZ4xCjAIBgNVBAUTATUxCzAJBgNV
+MIIDpjCCAo4CARAwDQYJKoZIhvcNAQEFBQAwgZ4xCjAIBgNVBAUTATUxCzAJBgNV
BAYTAlVTMQswCQYDVQQIEwJDQTESMBAGA1UEBxMJU3Vubnl2YWxlMRIwEAYDVQQK
EwlPcGVuU3RhY2sxETAPBgNVBAsTCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZr
ZXlzdG9uZUBvcGVuc3RhY2sub3JnMRQwEgYDVQQDEwtTZWxmIFNpZ25lZDAgFw0x
-MjExMDUxODE4MjRaGA8yMDcxMDQzMDE4MTgyNFowgZAxCzAJBgNVBAYTAlVTMQsw
+MzA3MDkxNjI1MDBaGA8yMDcyMDEwMTE2MjUwMFowgZAxCzAJBgNVBAYTAlVTMQsw
CQYDVQQIEwJDQTESMBAGA1UEBxMJU3Vubnl2YWxlMRIwEAYDVQQKEwlPcGVuU3Rh
Y2sxETAPBgNVBAsTCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZrZXlzdG9uZUBv
-cGVuc3RhY2sub3JnMRIwEAYDVQQDEwlsb2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEB
-BQADgY0AMIGJAoGBANRG3ZkIJ+NaY9smirkZ+Lzf1Ka18xOvc2kizemUMeAchs9h
-lP0Kpm8EBHal1vgzSuXncP8gyQ6nMZUw5NhFMZ1kLSfzoB/hCyTlIp/4VZbCAtn4
-3zlTUSgQQMH+6I4k4sZDOiIAE7yvzEMa71RkqBzduuFoeuhBm5oqmRa8kac5AgMB
-AAEwDQYJKoZIhvcNAQEFBQADgYEAJLnmyYiBDNdykLeh3+HXCOExUt49/OzomB6c
-6NWq3j7efYBfh6zCgyowx/v0hEVcxYBunTfXgOGunjx0u5X13PuLRO7Qxv6Crdy6
-st0mZ0itCsp58uGz5n+ZVhG//NiweTKw9M12Mejs0L/JGtf5gPBCFkVvrl8ffwRG
-060Ep/k=
+cGVuc3RhY2sub3JnMRIwEAYDVQQDEwlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQC5dpW18l3bs+Mcj/JdhaAa+qw1RJwShm06g+q38ZoC
+cCmRO3/XyHghgHWdVa+FKVm2ug923dE2PW4GSI1pZa3iqbT9Yj70nxN+0l94iym+
+v9/P7irolvo5OWBbBIJT1Ubjps5fJ//gz6BdmwS0FuOy2qfKPnPhyBDH2VawtOgY
+MLk+PSG3YQh7vM2YvDALPTPz/f4qPmhQpb69KBJQElFXPQ9Nu0ABCPWWC2tN87L5
+pakFw5zq46pttSJ7Izc8MXh3KQrh9FvjmiQuRnkMvQ/g887Sp6nEJ22ABPEFhuRr
+89aup6wRD2CkA/8L3zSB5BV7tTK4hQiq07cTnV9Dv6bfAgMBAAEwDQYJKoZIhvcN
+AQEFBQADggEBAIVz3ZwxSUF/y5ABmjnVIQaVVxH97bu07smFQUe0AB2I9R4xnBJ9
+jn93DpeixZvArCZuDuJEJvNER8S6L3r/OPMPrVzayxibXATaZRE8khMWEJpsnyeW
+8paA5NuZJwN2NjlPOmT47J1m7ZjLgkrVwjhwQZPMnh5kG9690TBJNhg9x3Z8f6p3
+iKj2AfZWGhp9Xr2xOZCpfvAZmyvKOMeuHVrRZ2VWGuzojQd7fjSEDw/+Tg8Gw1LV
+BQXjXiKQHsD1YID2a9Pe9yrBjO00ZMxMw8+wN9qrh+8vxfmwTO8tEkmcpvM4ivO3
+/oGGhQh6nSncERVI7rx+wBDnIHKBz6MU2Ow=
-----END CERTIFICATE-----
diff --git a/examples/pki/cms/auth_token_revoked.pem b/examples/pki/cms/auth_token_revoked.pem
index 842ff9bc..1435c1e9 100644
--- a/examples/pki/cms/auth_token_revoked.pem
+++ b/examples/pki/cms/auth_token_revoked.pem
@@ -1,5 +1,5 @@
-----BEGIN CMS-----
-MIIHVgYJKoZIhvcNAQcCoIIHRzCCB0MCAQExCTAHBgUrDgMCGjCCBeQGCSqGSIb3
+MIIH1wYJKoZIhvcNAQcCoIIHyDCCB8QCAQExCTAHBgUrDgMCGjCCBeQGCSqGSIb3
DQEHAaCCBdUEggXReyJhY2Nlc3MiOiB7InNlcnZpY2VDYXRhbG9nIjogW3siZW5k
cG9pbnRzIjogW3siYWRtaW5VUkwiOiAiaHR0cDovLzEyNy4wLjAuMTo4Nzc2L3Yx
LzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODliYjY2MTdhIiwgInJlZ2lvbiI6ICJy
@@ -31,12 +31,14 @@ ImlkIjogInRlbmFudF9pZDEifX0sICJ1c2VyIjogeyJ1c2VybmFtZSI6ICJyZXZv
a2VkX3VzZXJuYW1lMSIsICJyb2xlc19saW5rcyI6IFsicm9sZTEiLCJyb2xlMiJd
LCAiaWQiOiAicmV2b2tlZF91c2VyX2lkMSIsICJyb2xlcyI6IFt7Im5hbWUiOiAi
cm9sZTEifSwgeyJuYW1lIjogInJvbGUyIn1dLCAibmFtZSI6ICJyZXZva2VkX3Vz
-ZXJuYW1lMSJ9fX0NCjGCAUkwggFFAgEBMIGkMIGeMQowCAYDVQQFEwE1MQswCQYD
+ZXJuYW1lMSJ9fX0NCjGCAcowggHGAgEBMIGkMIGeMQowCAYDVQQFEwE1MQswCQYD
VQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVN1bm55dmFsZTESMBAGA1UE
ChMJT3BlblN0YWNrMREwDwYDVQQLEwhLZXlzdG9uZTElMCMGCSqGSIb3DQEJARYW
a2V5c3RvbmVAb3BlbnN0YWNrLm9yZzEUMBIGA1UEAxMLU2VsZiBTaWduZWQCAREw
-BwYFKw4DAhowDQYJKoZIhvcNAQEBBQAEgYDMKg2xebd6Ua2gxnNZBIHtDsRmfsGK
-tfD8k03XWWDnjrKqKtYC1BKFJAhYCGgVH8a+jhM4ye8BjUZ7F42AYdnI2CrdvDGX
-ULTe3iAW4WFrhvWB8KP2lllitY3fpbj+GyDwLqcMFALlWzYVioCzN00+MeCG8pUB
-vdK6NKiV9sCZjg==
+BwYFKw4DAhowDQYJKoZIhvcNAQEBBQAEggEAXY8JvllpyctcNlJByPLxhgLyRfFo
+Ew+8Yq3O4FxOyfVkINvOz4EHTipY0M/K8OLwfxpRt7o/iGLGRDBTI6Dd+erXsus8
+NecnNxcWN9RUE2CZhoGj/0nhnNEGF+9Mlv3tMBngwoUJg2paSw/Vn2Q7RaqbOC05
+aZOSDoSX7Zf0DIS/T0ZPnmOUb9+N25M20ctMHksPMEq0qyf2oove0O+WMa/cA8JT
+c2EAhew4WSD0Zv0GOAP30GS+hkNfA1GZTrvCQrpRs9jXhK4dR2bBsnUFVix1BEZ0
+sDhI8cXLvm16IpOO8ov6002ZoZhPn6Qo+0J8QOfdnjiwNnxLOEbuOIwPeQ==
-----END CMS-----
diff --git a/examples/pki/cms/auth_token_scoped.pem b/examples/pki/cms/auth_token_scoped.pem
index cc0da169..5c02c954 100644
--- a/examples/pki/cms/auth_token_scoped.pem
+++ b/examples/pki/cms/auth_token_scoped.pem
@@ -1,5 +1,5 @@
-----BEGIN CMS-----
-MIIHQAYJKoZIhvcNAQcCoIIHMTCCBy0CAQExCTAHBgUrDgMCGjCCBc4GCSqGSIb3
+MIIHwQYJKoZIhvcNAQcCoIIHsjCCB64CAQExCTAHBgUrDgMCGjCCBc4GCSqGSIb3
DQEHAaCCBb8EggW7eyJhY2Nlc3MiOiB7InNlcnZpY2VDYXRhbG9nIjogW3siZW5k
cG9pbnRzIjogW3siYWRtaW5VUkwiOiAiaHR0cDovLzEyNy4wLjAuMTo4Nzc2L3Yx
LzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODliYjY2MTdhIiwgInJlZ2lvbiI6ICJy
@@ -30,12 +30,15 @@ ZSwgImRlc2NyaXB0aW9uIjogbnVsbCwgIm5hbWUiOiAidGVuYW50X25hbWUxIiwg
ImlkIjogInRlbmFudF9pZDEifX0sICJ1c2VyIjogeyJ1c2VybmFtZSI6ICJ1c2Vy
X25hbWUxIiwgInJvbGVzX2xpbmtzIjogWyJyb2xlMSIsInJvbGUyIl0sICJpZCI6
ICJ1c2VyX2lkMSIsICJyb2xlcyI6IFt7Im5hbWUiOiAicm9sZTEifSwgeyJuYW1l
-IjogInJvbGUyIn1dLCAibmFtZSI6ICJ1c2VyX25hbWUxIn19fQ0KMYIBSTCCAUUC
+IjogInJvbGUyIn1dLCAibmFtZSI6ICJ1c2VyX25hbWUxIn19fQ0KMYIByjCCAcYC
AQEwgaQwgZ4xCjAIBgNVBAUTATUxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTES
MBAGA1UEBxMJU3Vubnl2YWxlMRIwEAYDVQQKEwlPcGVuU3RhY2sxETAPBgNVBAsT
CEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZrZXlzdG9uZUBvcGVuc3RhY2sub3Jn
MRQwEgYDVQQDEwtTZWxmIFNpZ25lZAIBETAHBgUrDgMCGjANBgkqhkiG9w0BAQEF
-AASBgEWUF++cnK20YBvO8kcIsVkCsg3M+oVAHGleCQZr8ho2yvgQ06hlPYl95Ih6
-+wIHsUlO1EUxCmNBAdydGDzuonWvkHMN/KMv/PW4EbiuawpvqYYLxqRg3ADjIMNl
-fxcgEbY34WAe3dYs2IAGiN70jFbqTr3ltxWHRTeeAqeltio9
+AASCAQCAtuVtqTU9h1uaRrYU1eusSnHwD6jizp/xltTrYTyFPfYjhJdglS+bjSeS
+Iau9pN3Tfug98ozUTJ5ByNepAQtxBxPz5bDXhBmAbU6ywaolqRAG+b/s2ShNGQ2a
+tn80NeZmDNbtoqdHVAkD3EZXjsEKr2w+3JTTF2indzczyGe5EeSfNUaT+ZhNEmPR
+Urob62t8atW+zehCSurpaa8pC5m1NcbK8Uu6Y+qO2m08KU9w5kmbOQtWAGCmtpIx
+F2yM1AbSgd90yzen7dv5mNkgZyzQ6SYgRUvkKOKnCyBb97EZK3ZR4qUxQzRYM++8
+g8HdaIfoYVPoPHqODet8Xmhw/Wtp
-----END CMS-----
diff --git a/examples/pki/cms/auth_token_unscoped.pem b/examples/pki/cms/auth_token_unscoped.pem
index 4b073e98..60649090 100644
--- a/examples/pki/cms/auth_token_unscoped.pem
+++ b/examples/pki/cms/auth_token_unscoped.pem
@@ -1,17 +1,19 @@
-----BEGIN CMS-----
-MIICpwYJKoZIhvcNAQcCoIICmDCCApQCAQExCTAHBgUrDgMCGjCCATUGCSqGSIb3
+MIIDKAYJKoZIhvcNAQcCoIIDGTCCAxUCAQExCTAHBgUrDgMCGjCCATUGCSqGSIb3
DQEHAaCCASYEggEieyJhY2Nlc3MiOiB7InRva2VuIjogeyJleHBpcmVzIjogIjIw
MTItMDgtMTdUMTU6MzU6MzRaIiwgImlkIjogIjAxZTAzMmM5OTZlZjQ0MDZiMTQ0
MzM1OTE1YTQxZTc5In0sICJzZXJ2aWNlQ2F0YWxvZyI6IHt9LCAidXNlciI6IHsi
dXNlcm5hbWUiOiAidXNlcl9uYW1lMSIsICJyb2xlc19saW5rcyI6IFtdLCAiaWQi
OiAiYzljODllM2JlM2VlNDUzZmJmMDBjNzk2NmY2ZDNmYmQiLCAicm9sZXMiOiBb
eyduYW1lJzogJ3JvbGUxJ30seyduYW1lJzogJ3JvbGUyJ30sXSwgIm5hbWUiOiAi
-dXNlcl9uYW1lMSJ9fX0xggFJMIIBRQIBATCBpDCBnjEKMAgGA1UEBRMBNTELMAkG
+dXNlcl9uYW1lMSJ9fX0xggHKMIIBxgIBATCBpDCBnjEKMAgGA1UEBRMBNTELMAkG
A1UEBhMCVVMxCzAJBgNVBAgTAkNBMRIwEAYDVQQHEwlTdW5ueXZhbGUxEjAQBgNV
BAoTCU9wZW5TdGFjazERMA8GA1UECxMIS2V5c3RvbmUxJTAjBgkqhkiG9w0BCQEW
FmtleXN0b25lQG9wZW5zdGFjay5vcmcxFDASBgNVBAMTC1NlbGYgU2lnbmVkAgER
-MAcGBSsOAwIaMA0GCSqGSIb3DQEBAQUABIGAvJ19wdrQi3umLzaUAt1Ju9Vrr0m9
-vvMEACRBGSiJB8J3R0VaSOqMb6QQYUhddrcaBX70roTA0W0fwU5vNShcTC/zvHSH
-uj8FpotvJLj0YiVzzhpYzKXN6vqBIryhKm5SE6MXBmRULuyPSpIGgLCYlAIaOwdD
-5s96C9aQukos8sU=
+MAcGBSsOAwIaMA0GCSqGSIb3DQEBAQUABIIBAFyD9IH2bXsafCTyHEWS28zBuq03
+ZNWXV4+0BfdMbX1ONkaQ7mLGRmfabLHwfE5RaSASFh/Doq7KTc8XrBVfTm9HQPGr
+TLZUawdYlyBFVq0PEE1cPvO9Blz4X/2Awcp/Q67YRd/oLCY2dFWMClMroXu1fy3P
+oFlpWPPhURrbU1GjhUgPIz0IxNGjfWEHVsb5kz7Bo4E8J3pgIkccm97XZZtiCwf7
+DVNj+Eb5mRegGG6IgSSRpZULgnCmSofQ3RnW3jSCkDxLXDQm9IsaaLJsuUFLylGs
+mB/98w9mP192IGl5MVr8/tANXwb5ok2VatUp/Ww1U0IlWbhN374PbK76vcE=
-----END CMS-----
diff --git a/examples/pki/cms/revocation_list.pem b/examples/pki/cms/revocation_list.pem
index a69278f9..bd22d3f2 100644
--- a/examples/pki/cms/revocation_list.pem
+++ b/examples/pki/cms/revocation_list.pem
@@ -1,12 +1,15 @@
-----BEGIN CMS-----
-MIIB2QYJKoZIhvcNAQcCoIIByjCCAcYCAQExCTAHBgUrDgMCGjBpBgkqhkiG9w0B
+MIICWgYJKoZIhvcNAQcCoIICSzCCAkcCAQExCTAHBgUrDgMCGjBpBgkqhkiG9w0B
BwGgXARaeyJyZXZva2VkIjpbeyJpZCI6IjdhY2ZjZmRhZjZhMTRhZWJlOTdjNjFj
NTk0N2JjNGQzIiwiZXhwaXJlcyI6IjIwMTItMDgtMTRUMTc6NTg6NDhaIn1dfQ0K
-MYIBSTCCAUUCAQEwgaQwgZ4xCjAIBgNVBAUTATUxCzAJBgNVBAYTAlVTMQswCQYD
+MYIByjCCAcYCAQEwgaQwgZ4xCjAIBgNVBAUTATUxCzAJBgNVBAYTAlVTMQswCQYD
VQQIEwJDQTESMBAGA1UEBxMJU3Vubnl2YWxlMRIwEAYDVQQKEwlPcGVuU3RhY2sx
ETAPBgNVBAsTCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZrZXlzdG9uZUBvcGVu
c3RhY2sub3JnMRQwEgYDVQQDEwtTZWxmIFNpZ25lZAIBETAHBgUrDgMCGjANBgkq
-hkiG9w0BAQEFAASBgK0KiADUUObQfhVE/zfyqQI/ROjRODXonVwAJE3WydMHHdXa
-TwY/wVTaK0PwvrM/uIph6KOxwH4QelP3V1zRh0SJKERHK1ftJ8xCSxQ4zFwtFzG4
-JTiPDhQcSi1swrUqy6WfVthCJKrLuTnqCP4bTE4bC8DNzMNvilRylNxSQK4g
+hkiG9w0BAQEFAASCAQC2f05VHM7zjNT3TBO80AmZ00n7AEWUjbFe5nqIM8kWGM83
+01Bi3uU/nQ0daAd3tqCmDL2EfETAjD+xnIzjlN6eIA74Vy51wFD/KiyWYPWzw8mH
+WcATHmE4E8kLdt8NhUodCY9TCFxcHJNDR1Eai/U7hH+5O4p9HcmMjv/GWegZL6HB
+Up9Cxu6haxvPFmYylzM6Qt0Ad/WiO/JZLPTA4qXJEJSa9EMFMb0c2wSDSn30swJe
+7J79VTFktTr2djv8KFvaHr4vLFYv2Y3ZkTeHqam0m91vllxLZJUP5QTSHjjY6LFE
+5eEjIlOv9wOOm1uTtPIq6pxCugU1Wm7gstkqr55R
-----END CMS-----
diff --git a/examples/pki/private/cakey.pem b/examples/pki/private/cakey.pem
index e73c13fc..86ff4cfa 100644
--- a/examples/pki/private/cakey.pem
+++ b/examples/pki/private/cakey.pem
@@ -1,16 +1,28 @@
-----BEGIN PRIVATE KEY-----
-MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBALzI17ExCaqdr7xY
-2Q5CBZ1bW1lsrXxS8eNJRdQtskDuQVAluY03/OGZd8HQYiiY/ci2tYy7BNICbh5G
-aO95eqTDykJR3liOYE/tHbY6puQlj2ZivmhlSd2d5d7lF0/H28RQsLu9VktMuw6q
-9DpDm35jfrr8LgSeA3MdVqcS/4OhAgMBAAECgYEAjY9xJd5mqDicCXj6MhXRzgAu
-TK0QnhQ4a72LDiLB8qx171qKe9mK18RTp9LReC3Yx8Qx+PhYEf5egnc7wq7uBgsk
-wAE7bPXBPRoxFxDHtZDRASAhWxX0gkfyO3uIy88HIiQlu51v1O4mSVyNpOZFnY2b
-ygLw8lg4AUJibSwE+50CQQDjWKluxXnifqoCn18BeT0FokBmV6ZLnRvHaroJP73O
-kPDINiBRPxDpX1cQpQ4hXkjSRM9RrUa4Z6hAEmAUGcoPAkEA1JP7omqY6bRH+tmE
-fM503jP5YiGNPB2UJRDPTXnbylII+pwf+hP0aW+2hnjm0cTAJ2yBNd9UnclLBsFO
-yABHTwJBAJIvp7s3tfkjE3TeP7v11nwx6ZElWSQT4RHomblqyET0RC+pRjyX/eri
-SFzGlYB1XQQABQNzFR9sX+7bIfaq4pcCQCHs1/zMnEi3z8D109IDNN19V/BUQHD2
-m3zq2NqZdv0r6GjuX6AObTQicvO0+clCaBQimeBaGuvvgvy5/vOmL7sCQQDgFxy/
-Yn5c6/jZDf2Vd/Jdk9tdV7147nC/A93c08BIWhD+jgPe/eIYMch61y7VczXizlb7
-M/BPhTX0/4yrL5Pg
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCh1U+N3g2cjFi7
+GeVf21FIv8MDhughFCey9rysAuqFONSFYo2rectLgpDtVy4BFFUFlxmh8Ci9TEZ5
+LiA31tbc4584GxvlLt4dg8aFsUJRBKq0L9i7W5v9uFpHrY1Zr+P4vwG+v7IWOuzw
+19f517eGpp6LLcj2vrpN9Yb63rrydKOqr0KJodMd+vFKmi+euFcPqs6sw1OiC5Dp
+JN479CGl2Fs1WzMoKDedRNiXG7ysrVrYQIkfMBABBPIwilq1xXZz9Ybo0PbNgOu6
+xpSsy9hq+IzxcwYsr5CwIcbqW6Ju+Ti2iBEaff20lW7dFzO4kwrcqOr9Jnn7qE8Y
+fJo9Hyj3AgMBAAECggEAPeEVaTaF190mNGyDczKmEv4X8CpOag+N2nVT0SXQTJ5d
+TJ9RckbAwB+tkMLr+Uev9tI+39e3jCI1NDK56QAB6jYy9D4RXYGdNoXji80qgVYa
+e4lsAr/Vlp8+DfhDew6xSbSnUytzSeLAJJsznvmn2Bmvt6ILHKXzEMoYEabGrtvk
+0n31mmd6sszW6i1cYEhr3gK/VXaO4gM1oWit9aeIJDg3/D3UNUW7aoCTeCz91Gif
+87/JH3UIPEIt960jb3oV7ltajRSpiSOfefJFwz/2n09+/P/Sg1+SWAraqkqaLqhO
+zoslYSYUuOQv+j97iD/tDVBjiWR1TrzQjf/3noOl+QKBgQDTExaIe0YYI8KdBNZ6
+1cG3vztNWDh0PaP1n0n/bJYAGmAfxfn/gSrABXfeIAjy01f76EK2lPa/i8+DR7vL
+dJnUMO10OxaIZKr+OtR1XrMM6kREj6H5yHTNz0sJ3hDEfwJ1BndqwrXlCLAe7upe
+veXI9LVfPjPVmf8t9UwyxtaNiwKBgQDERzCGEuyKIeSfgytcdknJ0W+AbdkshC92
+tZQPbI35YOLac2/y7GMjjf5Xg5VJRIYwXAG8ha+61Tvd7+qCVdzNyYfyOoBEE69B
+Gc9UdpXRfIjxokfidqh7mIIfjFNSI/UyVmvL9wrregXPcM+s7OlLC/0O82gOcNxU
+GKF3oP5XxQKBgQCPZEZIjcZ+m7yYQzMZ26FwnL9Cug4QGdgLAx2YIkJ8624l568A
+ftV2AcD+67Boll8NSSoZM3W1htuAifjwLNRcLKkD7yhNnGX1tC2lVqI4weWC1jjp
+od6H+q01lOC7PLWEntH9ey1q3M4ZFaGunz89l9CnVXCNScLri9sqG56iJQKBgHOc
+50UiInhe7HbU4ZauClq5Za9FhRXGqtqGrDbFn38UBavdMUTq3p6Txgwwcp/coBoe
+J9uu90razU+2QPESuGPy4IPa17DB04pKNKiwzSC+9T83cpY/hJCAzazdkDqi+Yv0
+Abz7wE/h6Ug+T+WxCt3sqtvCnjlbWzyh4YJAr3BtAoGBAIibPCEfVOwOfMOXkhIb
+liRVVGNxXQa6MwGVVfyR9gmlM85IjcBjh+Tf5+v3Mo286OlzLXQjfYW5pXR5Mgaw
+bKe+z5AqJlOsA+lJGTyCNnPKwaXAYHt8dZ41WhgzekibHCx7EQ+8jH1jkz2Gwou6
+MDbnRu+e0FCyRFSuhB9Cim/K
-----END PRIVATE KEY-----
diff --git a/examples/pki/private/signing_key.pem b/examples/pki/private/signing_key.pem
index df9b64db..acf84761 100644
--- a/examples/pki/private/signing_key.pem
+++ b/examples/pki/private/signing_key.pem
@@ -1,16 +1,28 @@
-----BEGIN PRIVATE KEY-----
-MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANBnphDSfn7OTmk/
-JOLgOxE0QwP6F/7VCglQH8X2L3hwHUKhCg3FG7YXV054ZAZ79DmSKcQT8cERGUmS
-tiP4XpD6wSC2eFEs6MxQoLnVwON0DJAZXLkPlTiNv6uR+M9pJ8WnsbAYz3iF+w/T
-aMLU2BZToEqgosfMViHDVtcdRJ9XAgMBAAECgYAqcJEO5+6+oACzyhoW4ZblwADN
-tIZibLvofZqa07GDE0HCKc1EVJl6EXLEFhw4fdGUT8GVnoIi0PqXUvsohBGtkmpM
-Ee+Yj5ii7VEL75Z5zzJZ50CM7vI0AqZ2WMIITjgsrMKdBh0tHolTCqenqv1t2/OZ
-dwAgPG1C90VsPgLW4QJBAOvuCwOZwAOlIygeSYfl9/aQuIQzP5yIQbv95Z+jeyii
-ly29FrPqhZvU4+hS7xUnT8X1d5XemsQTScoE/lF3LEkCQQDiIi5crENMdYX60ax7
-/6U25Ej0XyQ3Gt8ryYDoPIaeWSlRV5TQnYfY9CdQqJmTyBWYHNBOhjHupNX4AgWJ
-8y6fAkEAlYNZP4LkCGtSiE4JUzINnhfAlybTHSPMZJJWPoCfv/Sp0baO+J2a5lJX
-zBcipEkxaMZSbouPkMqYbIoVkRLw4QJAD8y5looGrbnsYYjy1zsWbQ5oNoLLQfpj
-q2iJ1DAea8PpCiDnaegHzNXKRW1yRYwOTjF9MG9Z38WumYRypJ/UGwJBAJShOlyg
-AA3ob9ajlJ3/NMNbIrVbDuG1c14HVHarnF9nrf8wmjACXP/rjFZo9tVAbQjG6kXH
-41oYgyhOVRYT578=
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDEwuiHTXfQoNQ7
+IXK0+YEVURd+pxJo0gPUFnYpOwfduTyu9FOBeo+Kc/+SS+6ZSKP/KyeIyc/XHBO5
+tIgPiLgAbRIRMF5Bva4+OzstCeGcgxkoditQZe/DwPc8V0s8rFE0owSnQIdvXT2G
+yWO3IGSdLgtwLX1XHmIgDiIteEnRXmdC2Sw1wbi2qlJkjK5isCfcADDgm/42wT/f
+92HHdBmI5b60gVOAam/PzR2rMjuA6TzevDgKMg+a+Y1LVfEGTdN1IyLKLsfHtJay
++vjFbSaNDn1r5Uq5c0uRykq8mPrqqkBLsbWSqSTNjFfObo743PHg0goYdrIYQ4wX
+ptxSJRylAgMBAAECggEBAIDQPVz/CXarI+ZGQotaYPisqx3+kN3QyDLcNaVOgRrW
+P3UmfVjh/QEeae3ECkONu9e8z9gMjyX7uqo0F3NcBWI6Bb79FGgjnuQc8OPOeUZ2
+yUyk+DxdT/eu5+04FQh2o387TjuU0lXFDBem1sI30cbZMyHQliMnwAPOXO+5tVH8
+PusGNBMVvoCyfnj52uVjmAjPqLXyOMcKEhuJFbhnUURKvzkHRf43SWQsb081eh2m
+ACQ7uNzX7vg3aPXxSZXY2+hHX67POdqosjddu6CfoXcEHAOAUujvTOFvd1gGRkRo
+uOi5hNQqcN5uaqeq9enVThINDyFMzngZBhMCzRTWeK0CgYEA4qUhB7lJZLt9niDW
+4Fudda1Pzu3XfxHsSG4D+xx5LunKb3ChG5x7PSLJvusfvnkm5fqhEEhbSVARo6Vn
+AAA52u5SPDDNwyk1ttvBR/Fc7eGwpbRQry2I6ui6baKiIOSV2K3vJlsSK8/GMQqu
+j0fstJuSvQR7Y6NUYxlWi+VNussCgYEA3j7tFAdGFc5JkeTHSzsU4h2+17uVDSSi
+yr7Duc9+9fwAbsO4go9x1CAOvV2r0WX10jPsTGg1d31pWLvJrS6QsAffmM+A0QIT
+eBX+umcavXWy69VExWa0xKU9wTE/nQvX9Fr8A+Klh/WfMcvoomK2zgOKoRSmes04
+WKYlHWsSaE8CgYBUYcZ6abG5n1SVmwRlY7asKWqdUE/7L2EZVlyFEYTMwp5r/zL8
+ZLY9fMZAHqoi8FhbJ4Tv2wChuv3WP66pgWwI5tIXNtRk5OLqwcakUmiW6IAsMYYY
+sotXam5+gx55wKFJmvh+/0k0ppbTi3aSQeUPGRz44sJNxnGUs8pVK3pVIQKBgQDD
+ga+lEtEAlbv6b7sx3wN79pbPyOBR84yRtkcPygzx74Gh7uL9V5rW9GyDAUgIqR0a
+kTqp7HI8b0KhIHFFu9TkRcjY8JFtS9o8pXy0FcdcK5H+DFq3HKag5ovwy5YeXTDY
+cMGJ2XOsqtIkSDCZySTvDgaBtVzOYoHS2jWEL5C92QKBgGmL2juXIB+HAi7UuKPg
+nWkVTikt5Zr2GNgYtso75E7+ljaRuf4D9eEBiOD1qYKQm8KvsiVzEs71BSmT1p1C
+b2hlM/5Crb7KumIkHTARQFr5NPwuBZ6NA6RLnd++vKi0WgOJtDAlR3bgwugfQdzZ
+4Isaq9Rgfa/EHCKB2weQ7c3r
-----END PRIVATE KEY-----
diff --git a/examples/pki/private/ssl_key.pem b/examples/pki/private/ssl_key.pem
index 2002bde6..e2e68379 100644
--- a/examples/pki/private/ssl_key.pem
+++ b/examples/pki/private/ssl_key.pem
@@ -1,16 +1,28 @@
-----BEGIN PRIVATE KEY-----
-MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBANRG3ZkIJ+NaY9sm
-irkZ+Lzf1Ka18xOvc2kizemUMeAchs9hlP0Kpm8EBHal1vgzSuXncP8gyQ6nMZUw
-5NhFMZ1kLSfzoB/hCyTlIp/4VZbCAtn43zlTUSgQQMH+6I4k4sZDOiIAE7yvzEMa
-71RkqBzduuFoeuhBm5oqmRa8kac5AgMBAAECgYBngOI94tcoKQO1cJaFaJ964Jyc
-aO1L9OmOIvVJ5gNnpiEpbwgpVY8PZGMUwwoNXV0wumfDTmYaafVoLD35IcvtcS3D
-Tmsm+zC3ZQYzbQrIkQrtXE+y4bMwtscOTd61YDFQE++0omg3qckVu8IYSdFtTb9D
-SjSsWMnYoDmGrBqCHQJBAP2jq2I5fMPSR3LY5FdejwhyUcqs6AKyJD0BDJzIhdV6
-d0InWWss/atR4sMnOX7WKIo1m4+X+0+T2F69kj9hge8CQQDWQKTvbvlDugiziwNc
-FRl+yC7YTJ34toRFI4xbszKL3vgk4KDgfSQeoPp9KeHXmjgTfXIOwSVI83QBoL1d
-LHFXAkEAglD9VVJEEDiSDSfy6hDjXGugKon8CqaMh+tqF4PPf4eUjqC5CJ/tFYDV
-CX+1wr01xw0UCAsGTDSiDstHwNjQcQJAAkF3+xVeBnqE8O77wBJwzEbrR1e3KhEx
-31B6f9SpKZPVZP4Ac5ydrrzfJkY0nIKBKKNfegxKijQV+pZop/x5zQJASGTmKcW2
-WKj4P8PiolVlWH2ZTARSschff5wDV6nBneb5zWNgpPORrSRPl9yrYrgqk4vvjLh5
-rUiR/G65ZjmbnA==
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC5dpW18l3bs+Mc
+j/JdhaAa+qw1RJwShm06g+q38ZoCcCmRO3/XyHghgHWdVa+FKVm2ug923dE2PW4G
+SI1pZa3iqbT9Yj70nxN+0l94iym+v9/P7irolvo5OWBbBIJT1Ubjps5fJ//gz6Bd
+mwS0FuOy2qfKPnPhyBDH2VawtOgYMLk+PSG3YQh7vM2YvDALPTPz/f4qPmhQpb69
+KBJQElFXPQ9Nu0ABCPWWC2tN87L5pakFw5zq46pttSJ7Izc8MXh3KQrh9FvjmiQu
+RnkMvQ/g887Sp6nEJ22ABPEFhuRr89aup6wRD2CkA/8L3zSB5BV7tTK4hQiq07cT
+nV9Dv6bfAgMBAAECggEBAIB1K5L/kZUITulMptGyKUgmkjq/D98g7u0Vy/CmTkcc
+Cx6F+LGsL9D8mfplDBKOpo4S530sfKk1+Uwu2ovDGqKhazQJ5ZMnz6gK7Ieg1ERD
+wDDURTIeyKf0HtJMGD0av2QU+GIeYXQEO446PhLCu+n42zkQ8tDS8xSJbCsu0odV
+ok6+i7nEg9sP4uDfAAtM8CUJbRpFTha+m2a7pOz3ylU7/ZV4FDIgJ+FEynaphXAo
+bZE4MX5I7A4DDBp7/9g9HsgefByY4xiABuk7Rsyztyf2TrJEtcsVhiV4sCIIHsow
+u60KGEcTQWj4npBIMgW1QUdrwmAAh/35gOjt9ZndgTkCgYEA2yT5DmihjVaNF65B
+8VtdFcpESr8rr6FBmJ7z31m7MufeV1Inc5GqCK9agRmpr5sTYcgFB9it2IhW2WsA
+xHv+7J04bd9DBtgTv58GWrISsCR/abMZnJrm+F5Rafk77jwjCx/SwFj79ybI83Ia
+VJYMd7jqkxc00+DZT/3QWZqRrlsCgYEA2KeBBqUVdCpwNiJpgFM18HWjJx36HRk7
+YoFapXot/6R6A/rYmS+/goBZt2CWqqGtnXqWEZvH+v4L+WlUmYQrWwtoxpdR1oXz
+EmlCxN7D9MbRVR7QVW24h5zdwPOlbCTGoKzowOs8UEjMfQ81zoMinLmcJgHQSyzs
+OawgSF+DmM0CgYBQz26EELNaMktvKxQoE3/c9CyAv8Q1TKqqxBq8BxPP7s7/tkzU
+AigIcdlW+Aapue7IxQCN5yocShJ0tE+hJPRZfpR7d7P4xx9pLxQhx766c4sEiEXu
+iPSZK/artHuUG1r01DRcN7QabJP3qeDpxjcswuTFfu49H5IjPD5jfGsyNwKBgFjh
+bvdQ5lo/xsUOnQV+HZTGTeaQT7l8TnZ85rkYRKKp0TysvgsqIYDiMuwd/fGGXnlK
+fyI+LG51pmftpD1OkZLKPXOrRHGjhjK5aCDn2rAimGI5P/KsDpXj7r1ntyeEdtAX
+32y1lIrDMtDjWomcFqkBJGQbPl540Xhfeub1+EDJAoGAUZGPT2itKnxEFsa1SKHW
+yLeEsag/a9imAVyizo1WJn2WJaUhi1aHK49w6JRowIAzXXb7zLQt7BL8v+ydPVw3
+eySpXGqFuN/Prm3So0SeWllWcPsKFAzjgE0CWjNuB0GlAZGOaJOcWUNoOZjX/SDC
+FpolIoaSad28tGc8tbEk3fU=
-----END PRIVATE KEY-----
diff --git a/keystone/assignment/__init__.py b/keystone/assignment/__init__.py
new file mode 100644
index 00000000..5a848308
--- /dev/null
+++ b/keystone/assignment/__init__.py
@@ -0,0 +1,18 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+# flake8: noqa
+
+# Copyright 2013 OpenStack LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from keystone.assignment.core import *
diff --git a/doc/source/_templates/.placeholder b/keystone/assignment/backends/__init__.py
index e69de29b..e69de29b 100644
--- a/doc/source/_templates/.placeholder
+++ b/keystone/assignment/backends/__init__.py
diff --git a/keystone/assignment/backends/kvs.py b/keystone/assignment/backends/kvs.py
new file mode 100644
index 00000000..30d7b2eb
--- /dev/null
+++ b/keystone/assignment/backends/kvs.py
@@ -0,0 +1,499 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from keystone import assignment
+from keystone import clean
+from keystone.common import dependency
+from keystone.common import kvs
+from keystone import exception
+from keystone import identity
+
+
+@dependency.requires('identity_api')
+class Assignment(kvs.Base, assignment.Driver):
+ def __init__(self):
+ super(Assignment, self).__init__()
+
+ # Public interface
+
+ def get_project(self, tenant_id):
+ try:
+ return self.db.get('tenant-%s' % tenant_id)
+ except exception.NotFound:
+ raise exception.ProjectNotFound(project_id=tenant_id)
+
+ def list_projects(self, domain_id=None):
+ project_keys = filter(lambda x: x.startswith("tenant-"),
+ self.db.keys())
+ project_refs = [self.db.get(key) for key in project_keys]
+
+ if domain_id:
+ self.get_domain(domain_id)
+ project_refs = filter(lambda x: domain_id in x['domain_id'],
+ project_refs)
+ return project_refs
+
+ def get_project_by_name(self, tenant_name, domain_id):
+ try:
+ return self.db.get('tenant_name-%s' % tenant_name)
+ except exception.NotFound:
+ raise exception.ProjectNotFound(project_id=tenant_name)
+
+ def get_project_users(self, tenant_id):
+ self.get_project(tenant_id)
+ user_keys = filter(lambda x: x.startswith("user-"), self.db.keys())
+ user_refs = [self.db.get(key) for key in user_keys]
+ user_refs = filter(lambda x: tenant_id in x['tenants'], user_refs)
+ return [identity.filter_user(user_ref) for user_ref in user_refs]
+
+ def _get_user(self, user_id):
+ try:
+ return self.db.get('user-%s' % user_id)
+ except exception.NotFound:
+ raise exception.UserNotFound(user_id=user_id)
+
+ def _get_user_by_name(self, user_name, domain_id):
+ try:
+ return self.db.get('user_name-%s' % user_name)
+ except exception.NotFound:
+ raise exception.UserNotFound(user_id=user_name)
+
+ def _get_metadata(self, user_id=None, tenant_id=None,
+ domain_id=None, group_id=None):
+ try:
+ if user_id:
+ if tenant_id:
+ return self.db.get('metadata-%s-%s' % (tenant_id,
+ user_id))
+ else:
+ return self.db.get('metadata-%s-%s' % (domain_id,
+ user_id))
+ else:
+ if tenant_id:
+ return self.db.get('metadata-%s-%s' % (tenant_id,
+ group_id))
+ else:
+ return self.db.get('metadata-%s-%s' % (domain_id,
+ group_id))
+ except exception.NotFound:
+ raise exception.MetadataNotFound()
+
+ def get_role(self, role_id):
+ try:
+ return self.db.get('role-%s' % role_id)
+ except exception.NotFound:
+ raise exception.RoleNotFound(role_id=role_id)
+
+ def list_roles(self):
+ role_ids = self.db.get('role_list', [])
+ return [self.get_role(x) for x in role_ids]
+
+ def get_projects_for_user(self, user_id):
+ user_ref = self._get_user(user_id)
+ return user_ref.get('tenants', [])
+
+ def add_role_to_user_and_project(self, user_id, tenant_id, role_id):
+ self.identity_api.get_user(user_id)
+ self.get_project(tenant_id)
+ self.get_role(role_id)
+ try:
+ metadata_ref = self._get_metadata(user_id, tenant_id)
+ except exception.MetadataNotFound:
+ metadata_ref = {}
+
+ try:
+ metadata_ref['roles'] = self._add_role_to_role_dicts(
+ role_id, False, metadata_ref.get('roles', []),
+ allow_existing=False)
+ except KeyError:
+ msg = ('User %s already has role %s in tenant %s'
+ % (user_id, role_id, tenant_id))
+ raise exception.Conflict(type='role grant', details=msg)
+
+ self._update_metadata(user_id, tenant_id, metadata_ref)
+
+ def remove_role_from_user_and_project(self, user_id, tenant_id, role_id):
+ try:
+ metadata_ref = self._get_metadata(user_id, tenant_id)
+ except exception.MetadataNotFound:
+ metadata_ref = {}
+
+ try:
+ metadata_ref['roles'] = self._remove_role_from_role_dicts(
+ role_id, False, metadata_ref.get('roles', []))
+ except KeyError:
+ raise exception.RoleNotFound(message=_(
+ 'Cannot remove role that has not been granted, %s') %
+ role_id)
+
+ if len(metadata_ref['roles']):
+ self._update_metadata(user_id, tenant_id, metadata_ref)
+ else:
+
+ self.db.delete('metadata-%s-%s' % (tenant_id, user_id))
+ user_ref = self._get_user(user_id)
+ tenants = set(user_ref.get('tenants', []))
+ tenants.remove(tenant_id)
+ user_ref['tenants'] = list(tenants)
+ self.identity_api.update_user(user_id, user_ref)
+
+ def list_role_assignments(self):
+ """List the role assignments.
+
+ The kvs backend stores role assignments as key-values:
+
+ "metadata-{target}-{actor}", with the value being a role list
+
+ i.e. "metadata-MyProjectID-MyUserID" [{'id': role1}, {'id': role2}]
+
+ ...so we enumerate the list and extract the targets, actors
+ and roles.
+
+ """
+ assignment_list = []
+ metadata_keys = filter(lambda x: x.startswith("metadata-"),
+ self.db.keys())
+ for key in metadata_keys:
+ template = {}
+ meta_id1 = key.split('-')[1]
+ meta_id2 = key.split('-')[2]
+ try:
+ self.get_project(meta_id1)
+ template['project_id'] = meta_id1
+ except exception.NotFound:
+ template['domain_id'] = meta_id1
+ try:
+ self._get_user(meta_id2)
+ template['user_id'] = meta_id2
+ except exception.NotFound:
+ template['group_id'] = meta_id2
+
+ entry = self.db.get(key)
+ for r in self._roles_from_role_dicts(entry.get('roles', {}),
+ False):
+ role_assignment = template.copy()
+ role_assignment['role_id'] = r
+ assignment_list.append(role_assignment)
+
+ return assignment_list
+
+ # CRUD
+ def create_project(self, tenant_id, tenant):
+ tenant['name'] = clean.project_name(tenant['name'])
+ try:
+ self.get_project(tenant_id)
+ except exception.ProjectNotFound:
+ pass
+ else:
+ msg = 'Duplicate ID, %s.' % tenant_id
+ raise exception.Conflict(type='tenant', details=msg)
+
+ try:
+ self.get_project_by_name(tenant['name'], tenant['domain_id'])
+ except exception.ProjectNotFound:
+ pass
+ else:
+ msg = 'Duplicate name, %s.' % tenant['name']
+ raise exception.Conflict(type='tenant', details=msg)
+
+ self.db.set('tenant-%s' % tenant_id, tenant)
+ self.db.set('tenant_name-%s' % tenant['name'], tenant)
+ return tenant
+
+ def update_project(self, tenant_id, tenant):
+ if 'name' in tenant:
+ tenant['name'] = clean.project_name(tenant['name'])
+ try:
+ existing = self.db.get('tenant_name-%s' % tenant['name'])
+ if existing and tenant_id != existing['id']:
+ msg = 'Duplicate name, %s.' % tenant['name']
+ raise exception.Conflict(type='tenant', details=msg)
+ except exception.NotFound:
+ pass
+ # get the old name and delete it too
+ try:
+ old_project = self.db.get('tenant-%s' % tenant_id)
+ except exception.NotFound:
+ raise exception.ProjectNotFound(project_id=tenant_id)
+ new_project = old_project.copy()
+ new_project.update(tenant)
+ new_project['id'] = tenant_id
+ self.db.delete('tenant_name-%s' % old_project['name'])
+ self.db.set('tenant-%s' % tenant_id, new_project)
+ self.db.set('tenant_name-%s' % new_project['name'], new_project)
+ return new_project
+
+ def delete_project(self, tenant_id):
+ try:
+ old_project = self.db.get('tenant-%s' % tenant_id)
+ except exception.NotFound:
+ raise exception.ProjectNotFound(project_id=tenant_id)
+ self.db.delete('tenant_name-%s' % old_project['name'])
+ self.db.delete('tenant-%s' % tenant_id)
+
+ def _create_metadata(self, user_id, tenant_id, metadata,
+ domain_id=None, group_id=None):
+
+ return self._update_metadata(user_id, tenant_id, metadata,
+ domain_id, group_id)
+
+ def _update_metadata(self, user_id, tenant_id, metadata,
+ domain_id=None, group_id=None):
+ if user_id:
+ if tenant_id:
+ self.db.set('metadata-%s-%s' % (tenant_id, user_id), metadata)
+ user_ref = self._get_user(user_id)
+ tenants = set(user_ref.get('tenants', []))
+ if tenant_id not in tenants:
+ tenants.add(tenant_id)
+ user_ref['tenants'] = list(tenants)
+ self.identity_api.update_user(user_id, user_ref)
+ else:
+ self.db.set('metadata-%s-%s' % (domain_id, user_id), metadata)
+ else:
+ if tenant_id:
+ self.db.set('metadata-%s-%s' % (tenant_id, group_id), metadata)
+ else:
+ self.db.set('metadata-%s-%s' % (domain_id, group_id), metadata)
+ return metadata
+
+ def create_role(self, role_id, role):
+ try:
+ self.get_role(role_id)
+ except exception.RoleNotFound:
+ pass
+ else:
+ msg = 'Duplicate ID, %s.' % role_id
+ raise exception.Conflict(type='role', details=msg)
+
+ for role_ref in self.list_roles():
+ if role['name'] == role_ref['name']:
+ msg = 'Duplicate name, %s.' % role['name']
+ raise exception.Conflict(type='role', details=msg)
+ self.db.set('role-%s' % role_id, role)
+ role_list = set(self.db.get('role_list', []))
+ role_list.add(role_id)
+ self.db.set('role_list', list(role_list))
+ return role
+
+ def update_role(self, role_id, role):
+ old_role_ref = None
+ for role_ref in self.list_roles():
+ if role['name'] == role_ref['name'] and role_id != role_ref['id']:
+ msg = 'Duplicate name, %s.' % role['name']
+ raise exception.Conflict(type='role', details=msg)
+ if role_id == role_ref['id']:
+ old_role_ref = role_ref
+ if old_role_ref is None:
+ raise exception.RoleNotFound(role_id=role_id)
+ new_role = old_role_ref.copy()
+ new_role.update(role)
+ new_role['id'] = role_id
+ self.db.set('role-%s' % role_id, new_role)
+ return role
+
+ def delete_role(self, role_id):
+ self.get_role(role_id)
+ metadata_keys = filter(lambda x: x.startswith("metadata-"),
+ self.db.keys())
+ for key in metadata_keys:
+ meta_id1 = key.split('-')[1]
+ meta_id2 = key.split('-')[2]
+ try:
+ self.delete_grant(role_id, project_id=meta_id1,
+ user_id=meta_id2)
+ except exception.NotFound:
+ pass
+ try:
+ self.delete_grant(role_id, project_id=meta_id1,
+ group_id=meta_id2)
+ except exception.NotFound:
+ pass
+ try:
+ self.delete_grant(role_id, domain_id=meta_id1,
+ user_id=meta_id2)
+ except exception.NotFound:
+ pass
+ try:
+ self.delete_grant(role_id, domain_id=meta_id1,
+ group_id=meta_id2)
+ except exception.NotFound:
+ pass
+ self.db.delete('role-%s' % role_id)
+ role_list = set(self.db.get('role_list', []))
+ role_list.remove(role_id)
+ self.db.set('role_list', list(role_list))
+
+ def create_grant(self, role_id, user_id=None, group_id=None,
+ domain_id=None, project_id=None,
+ inherited_to_projects=False):
+
+ self.get_role(role_id)
+ if user_id:
+ self.identity_api.get_user(user_id)
+ if group_id:
+ self.identity_api.get_group(group_id)
+ if domain_id:
+ self.get_domain(domain_id)
+ if project_id:
+ self.get_project(project_id)
+
+ try:
+ metadata_ref = self._get_metadata(user_id, project_id,
+ domain_id, group_id)
+ except exception.MetadataNotFound:
+ metadata_ref = {}
+
+ metadata_ref['roles'] = self._add_role_to_role_dicts(
+ role_id, inherited_to_projects, metadata_ref.get('roles', []))
+
+ self._update_metadata(user_id, project_id, metadata_ref,
+ domain_id, group_id)
+
+ def list_grants(self, user_id=None, group_id=None,
+ domain_id=None, project_id=None,
+ inherited_to_projects=False):
+ if user_id:
+ self.identity_api.get_user(user_id)
+ if group_id:
+ self.identity_api.get_group(group_id)
+ if domain_id:
+ self.get_domain(domain_id)
+ if project_id:
+ self.get_project(project_id)
+
+ try:
+ metadata_ref = self._get_metadata(user_id, project_id,
+ domain_id, group_id)
+ except exception.MetadataNotFound:
+ metadata_ref = {}
+
+ return [self.get_role(x) for x in
+ self._roles_from_role_dicts(metadata_ref.get('roles', []),
+ inherited_to_projects)]
+
+ def get_grant(self, role_id, user_id=None, group_id=None,
+ domain_id=None, project_id=None,
+ inherited_to_projects=False):
+ self.get_role(role_id)
+ if user_id:
+ self.identity_api.get_user(user_id)
+ if group_id:
+ self.get_group(group_id)
+ if domain_id:
+ self.get_domain(domain_id)
+ if project_id:
+ self.get_project(project_id)
+
+ try:
+ metadata_ref = self._get_metadata(user_id, project_id,
+ domain_id, group_id)
+ except exception.MetadataNotFound:
+ metadata_ref = {}
+
+ role_ids = set(self._roles_from_role_dicts(
+ metadata_ref.get('roles', []), inherited_to_projects))
+
+ if role_id not in role_ids:
+ raise exception.RoleNotFound(role_id=role_id)
+ return self.get_role(role_id)
+
+ def delete_grant(self, role_id, user_id=None, group_id=None,
+ domain_id=None, project_id=None,
+ inherited_to_projects=False):
+ self.get_role(role_id)
+ if user_id:
+ self.identity_api.get_user(user_id)
+ if group_id:
+ self.identity_api.get_group(group_id)
+ if domain_id:
+ self.get_domain(domain_id)
+ if project_id:
+ self.get_project(project_id)
+
+ try:
+ metadata_ref = self._get_metadata(user_id, project_id,
+ domain_id, group_id)
+ except exception.MetadataNotFound:
+ metadata_ref = {}
+
+ try:
+ metadata_ref['roles'] = self._remove_role_from_role_dicts(
+ role_id, inherited_to_projects, metadata_ref.get('roles', []))
+ except KeyError:
+ raise exception.RoleNotFound(role_id=role_id)
+
+ self._update_metadata(user_id, project_id, metadata_ref,
+ domain_id, group_id)
+
+ # domain crud
+
+ def create_domain(self, domain_id, domain):
+ try:
+ self.get_domain(domain_id)
+ except exception.DomainNotFound:
+ pass
+ else:
+ msg = 'Duplicate ID, %s.' % domain_id
+ raise exception.Conflict(type='domain', details=msg)
+
+ try:
+ self.get_domain_by_name(domain['name'])
+ except exception.DomainNotFound:
+ pass
+ else:
+ msg = 'Duplicate name, %s.' % domain['name']
+ raise exception.Conflict(type='domain', details=msg)
+
+ self.db.set('domain-%s' % domain_id, domain)
+ self.db.set('domain_name-%s' % domain['name'], domain)
+ domain_list = set(self.db.get('domain_list', []))
+ domain_list.add(domain_id)
+ self.db.set('domain_list', list(domain_list))
+ return domain
+
+ def list_domains(self):
+ domain_ids = self.db.get('domain_list', [])
+ return [self.get_domain(x) for x in domain_ids]
+
+ def get_domain(self, domain_id):
+ try:
+ return self.db.get('domain-%s' % domain_id)
+ except exception.NotFound:
+ raise exception.DomainNotFound(domain_id=domain_id)
+
+ def get_domain_by_name(self, domain_name):
+ try:
+ return self.db.get('domain_name-%s' % domain_name)
+ except exception.NotFound:
+ raise exception.DomainNotFound(domain_id=domain_name)
+
+ def update_domain(self, domain_id, domain):
+ orig_domain = self.get_domain(domain_id)
+ domain['id'] = domain_id
+ self.db.set('domain-%s' % domain_id, domain)
+ self.db.set('domain_name-%s' % domain['name'], domain)
+ if domain['name'] != orig_domain['name']:
+ self.db.delete('domain_name-%s' % orig_domain['name'])
+ return domain
+
+ def delete_domain(self, domain_id):
+ domain = self.get_domain(domain_id)
+ self.db.delete('domain-%s' % domain_id)
+ self.db.delete('domain_name-%s' % domain['name'])
+ domain_list = set(self.db.get('domain_list', []))
+ domain_list.remove(domain_id)
+ self.db.set('domain_list', list(domain_list))
diff --git a/keystone/assignment/backends/ldap.py b/keystone/assignment/backends/ldap.py
new file mode 100644
index 00000000..9b273e40
--- /dev/null
+++ b/keystone/assignment/backends/ldap.py
@@ -0,0 +1,543 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012-2013 OpenStack LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+from __future__ import absolute_import
+
+import uuid
+
+import ldap as ldap
+
+from keystone import assignment
+from keystone import clean
+from keystone.common import dependency
+from keystone.common import ldap as common_ldap
+from keystone.common import logging
+from keystone.common import models
+from keystone import config
+from keystone import exception
+from keystone.identity.backends import ldap as ldap_identity
+
+
+CONF = config.CONF
+LOG = logging.getLogger(__name__)
+
+DEFAULT_DOMAIN = {
+ 'id': CONF.identity.default_domain_id,
+ 'name': 'Default',
+ 'enabled': True
+}
+
+
+@dependency.requires('identity_api')
+class Assignment(assignment.Driver):
+ def __init__(self):
+ super(Assignment, self).__init__()
+ self.LDAP_URL = CONF.ldap.url
+ self.LDAP_USER = CONF.ldap.user
+ self.LDAP_PASSWORD = CONF.ldap.password
+ self.suffix = CONF.ldap.suffix
+
+ #These are the only deep dependency from assignment back
+ #to identity. The assumption is that if you are using
+ #LDAP for assignments, you are using it for Id as well.
+ self.user = ldap_identity.UserApi(CONF)
+ self.group = ldap_identity.GroupApi(CONF)
+
+ self.project = ProjectApi(CONF)
+ self.role = RoleApi(CONF)
+ self._identity_api = None
+
+ def get_project(self, tenant_id):
+ return self._set_default_domain(self.project.get(tenant_id))
+
+ def list_projects(self, domain_id=None):
+ # We don't support multiple domains within this driver, so ignore
+ # any domain passed.
+ return self._set_default_domain(self.project.get_all())
+
+ def get_project_by_name(self, tenant_name, domain_id):
+ self._validate_default_domain_id(domain_id)
+ return self._set_default_domain(self.project.get_by_name(tenant_name))
+
+ def create_project(self, tenant_id, tenant):
+ tenant = self._validate_default_domain(tenant)
+ tenant['name'] = clean.project_name(tenant['name'])
+ data = tenant.copy()
+ if 'id' not in data or data['id'] is None:
+ data['id'] = str(uuid.uuid4().hex)
+ if 'description' in data and data['description'] in ['', None]:
+ data.pop('description')
+ return self._set_default_domain(self.project.create(data))
+
+ def update_project(self, tenant_id, tenant):
+ tenant = self._validate_default_domain(tenant)
+ if 'name' in tenant:
+ tenant['name'] = clean.project_name(tenant['name'])
+ return self._set_default_domain(self.project.update(tenant_id, tenant))
+
+ def _get_metadata(self, user_id=None, tenant_id=None,
+ domain_id=None, group_id=None):
+
+ def _get_roles_for_just_user_and_project(user_id, tenant_id):
+ self.identity_api.get_user(user_id)
+ self.get_project(tenant_id)
+ user_dn = self.user._id_to_dn(user_id)
+ return [self.role._dn_to_id(a.role_dn)
+ for a in self.role.get_role_assignments
+ (self.project._id_to_dn(tenant_id))
+ if a.user_dn == user_dn]
+
+ if domain_id is not None:
+ msg = 'Domain metadata not supported by LDAP'
+ raise exception.NotImplemented(message=msg)
+ if (not self.get_project(tenant_id) or
+ not self.identity_api.get_user(user_id)):
+ return {}
+
+ metadata_ref = _get_roles_for_just_user_and_project(user_id, tenant_id)
+ if not metadata_ref:
+ return {}
+ return {'roles': [self._role_to_dict(r, False) for r in metadata_ref]}
+
+ def get_role(self, role_id):
+ return self.role.get(role_id)
+
+ def list_roles(self):
+ return self.role.get_all()
+
+ def get_projects_for_user(self, user_id):
+ self.identity_api.get_user(user_id)
+ user_dn = self.user._id_to_dn(user_id)
+ associations = (self.role.list_project_roles_for_user
+ (user_dn, self.project.tree_dn))
+ return [p['id'] for p in
+ self.project.get_user_projects(user_dn, associations)]
+
+ def get_project_users(self, tenant_id):
+ self.get_project(tenant_id)
+ tenant_dn = self.project._id_to_dn(tenant_id)
+ rolegrants = self.role.get_role_assignments(tenant_dn)
+ users = [self.user.get_filtered(self.user._dn_to_id(user_id))
+ for user_id in
+ self.project.get_user_dns(tenant_id, rolegrants)]
+ return self._set_default_domain(users)
+
+ def _subrole_id_to_dn(self, role_id, tenant_id):
+ if tenant_id is None:
+ return self.role._id_to_dn(role_id)
+ else:
+ return '%s=%s,%s' % (self.role.id_attr,
+ ldap.dn.escape_dn_chars(role_id),
+ self.project._id_to_dn(tenant_id))
+
+ def add_role_to_user_and_project(self, user_id, tenant_id, role_id):
+ self.identity_api.get_user(user_id)
+ self.get_project(tenant_id)
+ self.get_role(role_id)
+ user_dn = self.user._id_to_dn(user_id)
+ role_dn = self._subrole_id_to_dn(role_id, tenant_id)
+ self.role.add_user(role_id, role_dn, user_dn, user_id, tenant_id)
+ tenant_dn = self.project._id_to_dn(tenant_id)
+ return UserRoleAssociation(
+ role_dn=role_dn,
+ user_dn=user_dn,
+ tenant_dn=tenant_dn)
+
+ def _create_metadata(self, user_id, tenant_id, metadata):
+ return {}
+
+ def create_role(self, role_id, role):
+ try:
+ self.get_role(role_id)
+ except exception.NotFound:
+ pass
+ else:
+ msg = 'Duplicate ID, %s.' % role_id
+ raise exception.Conflict(type='role', details=msg)
+
+ try:
+ self.role.get_by_name(role['name'])
+ except exception.NotFound:
+ pass
+ else:
+ msg = 'Duplicate name, %s.' % role['name']
+ raise exception.Conflict(type='role', details=msg)
+
+ return self.role.create(role)
+
+ def delete_role(self, role_id):
+ return self.role.delete(role_id, self.project.tree_dn)
+
+ def delete_project(self, tenant_id):
+ if self.project.subtree_delete_enabled:
+ self.project.deleteTree(id)
+ else:
+ tenant_dn = self.project._id_to_dn(tenant_id)
+ self.role.roles_delete_subtree_by_project(tenant_dn)
+ self.project.delete(tenant_id)
+
+ def remove_role_from_user_and_project(self, user_id, tenant_id, role_id):
+ role_dn = self._subrole_id_to_dn(role_id, tenant_id)
+ return self.role.delete_user(role_dn,
+ self.user._id_to_dn(user_id),
+ self.project._id_to_dn(tenant_id),
+ user_id, role_id)
+
+ def update_role(self, role_id, role):
+ self.get_role(role_id)
+ self.role.update(role_id, role)
+
+ def create_domain(self, domain_id, domain):
+ if domain_id == CONF.identity.default_domain_id:
+ msg = 'Duplicate ID, %s.' % domain_id
+ raise exception.Conflict(type='domain', details=msg)
+ raise exception.Forbidden('Domains are read-only against LDAP')
+
+ def get_domain(self, domain_id):
+ self._validate_default_domain_id(domain_id)
+ return DEFAULT_DOMAIN
+
+ def update_domain(self, domain_id, domain):
+ self._validate_default_domain_id(domain_id)
+ raise exception.Forbidden('Domains are read-only against LDAP')
+
+ def delete_domain(self, domain_id):
+ self._validate_default_domain_id(domain_id)
+ raise exception.Forbidden('Domains are read-only against LDAP')
+
+ def list_domains(self):
+ return [assignment.DEFAULT_DOMAIN]
+
+#Bulk actions on User From identity
+ def delete_user(self, user_id):
+ user_dn = self.user._id_to_dn(user_id)
+ for ref in self.role.list_global_roles_for_user(user_dn):
+ self.role.delete_user(ref.role_dn, ref.user_dn, ref.project_dn,
+ user_id, self.role._dn_to_id(ref.role_dn))
+ for ref in self.role.list_project_roles_for_user(user_dn,
+ self.project.tree_dn):
+ self.role.delete_user(ref.role_dn, ref.user_dn, ref.project_dn,
+ user_id, self.role._dn_to_id(ref.role_dn))
+
+ user = self.user.get(user_id)
+ if hasattr(user, 'tenant_id'):
+ self.project.remove_user(user.tenant_id,
+ self.user._id_to_dn(user_id))
+
+ #LDAP assignments only supports LDAP identity. Assignments under identity
+ #are already deleted
+ def delete_group(self, group_id):
+ if not self.group.subtree_delete_enabled:
+ # TODO(spzala): this is only placeholder for group and domain
+ # role support which will be added under bug 1101287
+ conn = self.group.get_connection()
+ query = '(objectClass=%s)' % self.group.object_class
+ dn = None
+ dn = self.group._id_to_dn(id)
+ if dn:
+ try:
+ roles = conn.search_s(dn, ldap.SCOPE_ONELEVEL,
+ query, ['%s' % '1.1'])
+ for role_dn, _ in roles:
+ conn.delete_s(role_dn)
+ except ldap.NO_SUCH_OBJECT:
+ pass
+
+
+# TODO(termie): turn this into a data object and move logic to driver
+class ProjectApi(common_ldap.EnabledEmuMixIn, common_ldap.BaseLdap):
+ DEFAULT_OU = 'ou=Groups'
+ DEFAULT_STRUCTURAL_CLASSES = []
+ DEFAULT_OBJECTCLASS = 'groupOfNames'
+ DEFAULT_ID_ATTR = 'cn'
+ DEFAULT_MEMBER_ATTRIBUTE = 'member'
+ DEFAULT_ATTRIBUTE_IGNORE = []
+ NotFound = exception.ProjectNotFound
+ notfound_arg = 'project_id' # NOTE(yorik-sar): while options_name = tenant
+ options_name = 'tenant'
+ attribute_mapping = {'name': 'ou',
+ 'description': 'description',
+ 'tenantId': 'cn',
+ 'enabled': 'enabled',
+ 'domain_id': 'domain_id'}
+ model = models.Project
+
+ def __init__(self, conf):
+ super(ProjectApi, self).__init__(conf)
+ self.attribute_mapping['name'] = conf.ldap.tenant_name_attribute
+ self.attribute_mapping['description'] = conf.ldap.tenant_desc_attribute
+ self.attribute_mapping['enabled'] = conf.ldap.tenant_enabled_attribute
+ self.attribute_mapping['domain_id'] = (
+ conf.ldap.tenant_domain_id_attribute)
+ self.member_attribute = (getattr(conf.ldap, 'tenant_member_attribute')
+ or self.DEFAULT_MEMBER_ATTRIBUTE)
+ self.attribute_ignore = (getattr(conf.ldap, 'tenant_attribute_ignore')
+ or self.DEFAULT_ATTRIBUTE_IGNORE)
+
+ def create(self, values):
+ self.affirm_unique(values)
+ data = values.copy()
+ if data.get('id') is None:
+ data['id'] = uuid.uuid4().hex
+ return super(ProjectApi, self).create(data)
+
+ def get_user_projects(self, user_dn, associations):
+ """Returns list of tenants a user has access to
+ """
+
+ project_ids = set()
+ for assoc in associations:
+ project_ids.add(self._dn_to_id(assoc.project_dn))
+ projects = []
+ for project_id in project_ids:
+ #slower to get them one at a time, but a huge list could blow out
+ #the connection. This is the safer way
+ projects.append(self.get(project_id))
+ return projects
+
+ def add_user(self, tenant_id, user_dn):
+ conn = self.get_connection()
+ try:
+ conn.modify_s(
+ self._id_to_dn(tenant_id),
+ [(ldap.MOD_ADD,
+ self.member_attribute,
+ user_dn)])
+ except ldap.TYPE_OR_VALUE_EXISTS:
+ # As adding a user to a tenant is done implicitly in several
+ # places, and is not part of the exposed API, it's easier for us to
+ # just ignore this instead of raising exception.Conflict.
+ pass
+
+ def remove_user(self, tenant_id, user_dn, user_id):
+ conn = self.get_connection()
+ try:
+ conn.modify_s(self._id_to_dn(tenant_id),
+ [(ldap.MOD_DELETE,
+ self.member_attribute,
+ user_dn)])
+ except ldap.NO_SUCH_ATTRIBUTE:
+ raise exception.NotFound(user_id)
+
+ def get_user_dns(self, tenant_id, rolegrants, role_dn=None):
+ tenant = self._ldap_get(tenant_id)
+ res = set()
+ if not role_dn:
+ # Get users who have default tenant mapping
+ for user_dn in tenant[1].get(self.member_attribute, []):
+ if self.use_dumb_member and user_dn == self.dumb_member:
+ continue
+ res.add(user_dn)
+
+ # Get users who are explicitly mapped via a tenant
+ for rolegrant in rolegrants:
+ if role_dn is None or rolegrant.role_dn == role_dn:
+ res.add(rolegrant.user_dn)
+ return list(res)
+
+ def update(self, id, values):
+ old_obj = self.get(id)
+ if old_obj['name'] != values['name']:
+ msg = 'Changing Name not supported by LDAP'
+ raise exception.NotImplemented(message=msg)
+ return super(ProjectApi, self).update(id, values, old_obj)
+
+
+class UserRoleAssociation(object):
+ """Role Grant model."""
+
+ def __init__(self, user_dn=None, role_dn=None, tenant_dn=None,
+ *args, **kw):
+ self.user_dn = user_dn
+ self.role_dn = role_dn
+ self.project_dn = tenant_dn
+
+
+class GroupRoleAssociation(object):
+ """Role Grant model."""
+
+ def __init__(self, group_dn=None, role_dn=None, tenant_dn=None,
+ *args, **kw):
+ self.group_dn = group_dn
+ self.role_dn = role_dn
+ self.project_dn = tenant_dn
+
+
+# TODO(termie): turn this into a data object and move logic to driver
+class RoleApi(common_ldap.BaseLdap):
+ DEFAULT_OU = 'ou=Roles'
+ DEFAULT_STRUCTURAL_CLASSES = []
+ DEFAULT_OBJECTCLASS = 'organizationalRole'
+ DEFAULT_MEMBER_ATTRIBUTE = 'roleOccupant'
+ DEFAULT_ATTRIBUTE_IGNORE = []
+ NotFound = exception.RoleNotFound
+ options_name = 'role'
+ attribute_mapping = {'name': 'ou',
+ #'serviceId': 'service_id',
+ }
+ model = models.Role
+
+ def __init__(self, conf):
+ super(RoleApi, self).__init__(conf)
+ self.attribute_mapping['name'] = conf.ldap.role_name_attribute
+ self.member_attribute = (getattr(conf.ldap, 'role_member_attribute')
+ or self.DEFAULT_MEMBER_ATTRIBUTE)
+ self.attribute_ignore = (getattr(conf.ldap, 'role_attribute_ignore')
+ or self.DEFAULT_ATTRIBUTE_IGNORE)
+
+ def get(self, id, filter=None):
+ model = super(RoleApi, self).get(id, filter)
+ return model
+
+ def create(self, values):
+ return super(RoleApi, self).create(values)
+
+ def add_user(self, role_id, role_dn, user_dn, user_id, tenant_id=None):
+ conn = self.get_connection()
+ try:
+ conn.modify_s(role_dn, [(ldap.MOD_ADD,
+ self.member_attribute, user_dn)])
+ except ldap.TYPE_OR_VALUE_EXISTS:
+ msg = ('User %s already has role %s in tenant %s'
+ % (user_id, role_id, tenant_id))
+ raise exception.Conflict(type='role grant', details=msg)
+ except ldap.NO_SUCH_OBJECT:
+ if tenant_id is None or self.get(role_id) is None:
+ raise Exception(_("Role %s not found") % (role_id,))
+
+ attrs = [('objectClass', [self.object_class]),
+ (self.member_attribute, [user_dn])]
+
+ if self.use_dumb_member:
+ attrs[1][1].append(self.dumb_member)
+ try:
+ conn.add_s(role_dn, attrs)
+ except Exception as inst:
+ raise inst
+
+ def delete_user(self, role_dn, user_dn, tenant_dn,
+ user_id, role_id):
+ conn = self.get_connection()
+ try:
+ conn.modify_s(role_dn, [(ldap.MOD_DELETE,
+ self.member_attribute, user_dn)])
+ except ldap.NO_SUCH_OBJECT:
+ if tenant_dn is None:
+ raise exception.RoleNotFound(role_id=role_id)
+ attrs = [('objectClass', [self.object_class]),
+ (self.member_attribute, [user_dn])]
+
+ if self.use_dumb_member:
+ attrs[1][1].append(self.dumb_member)
+ try:
+ conn.add_s(role_dn, attrs)
+ except Exception as inst:
+ raise inst
+ except ldap.NO_SUCH_ATTRIBUTE:
+ raise exception.UserNotFound(user_id=user_id)
+
+ def get_role_assignments(self, tenant_dn):
+ conn = self.get_connection()
+ query = '(objectClass=%s)' % self.object_class
+
+ try:
+ roles = conn.search_s(tenant_dn, ldap.SCOPE_ONELEVEL, query)
+ except ldap.NO_SUCH_OBJECT:
+ return []
+
+ res = []
+ for role_dn, attrs in roles:
+ try:
+ user_dns = attrs[self.member_attribute]
+ except KeyError:
+ continue
+ for user_dn in user_dns:
+ if self.use_dumb_member and user_dn == self.dumb_member:
+ continue
+ res.append(UserRoleAssociation(
+ user_dn=user_dn,
+ role_dn=role_dn,
+ tenant_dn=tenant_dn))
+
+ return res
+
+ def list_global_roles_for_user(self, user_dn):
+ roles = self.get_all('(%s=%s)' % (self.member_attribute, user_dn))
+ return [UserRoleAssociation(
+ role_dn=role.dn,
+ user_dn=user_dn) for role in roles]
+
+ def list_project_roles_for_user(self, user_dn, project_subtree):
+ conn = self.get_connection()
+ query = '(&(objectClass=%s)(%s=%s))' % (self.object_class,
+ self.member_attribute,
+ user_dn)
+ try:
+ roles = conn.search_s(project_subtree,
+ ldap.SCOPE_SUBTREE,
+ query)
+ except ldap.NO_SUCH_OBJECT:
+ return []
+
+ res = []
+ for role_dn, _ in roles:
+ #ldap.dn.dn2str returns an array, where the first
+ #element is the first segment.
+ #For a role assignment, this contains the role ID,
+ #The remainder is the DN of the tenant.
+ tenant = ldap.dn.str2dn(role_dn)
+ tenant.pop(0)
+ tenant_dn = ldap.dn.dn2str(tenant)
+ res.append(UserRoleAssociation(
+ user_dn=user_dn,
+ role_dn=role_dn,
+ tenant_dn=tenant_dn))
+ return res
+
+ def roles_delete_subtree_by_project(self, tenant_dn):
+ conn = self.get_connection()
+ query = '(objectClass=%s)' % self.object_class
+ try:
+ roles = conn.search_s(tenant_dn, ldap.SCOPE_ONELEVEL, query)
+ for role_dn, _ in roles:
+ try:
+ conn.delete_s(role_dn)
+ except Exception as inst:
+ raise inst
+ except ldap.NO_SUCH_OBJECT:
+ pass
+
+ def update(self, role_id, role):
+ if role['id'] != role_id:
+ raise exception.ValidationError('Cannot change role ID')
+ try:
+ old_name = self.get_by_name(role['name'])
+ raise exception.Conflict('Cannot duplicate name %s' % old_name)
+ except exception.NotFound:
+ pass
+ return super(RoleApi, self).update(role_id, role)
+
+ def delete(self, id, tenant_dn):
+ conn = self.get_connection()
+ query = '(&(objectClass=%s)(%s=%s))' % (self.object_class,
+ self.id_attr, id)
+ try:
+ for role_dn, _ in conn.search_s(tenant_dn,
+ ldap.SCOPE_SUBTREE,
+ query):
+ conn.delete_s(role_dn)
+ except ldap.NO_SUCH_OBJECT:
+ pass
+ super(RoleApi, self).delete(id)
diff --git a/keystone/assignment/backends/sql.py b/keystone/assignment/backends/sql.py
new file mode 100644
index 00000000..cd2a0a5c
--- /dev/null
+++ b/keystone/assignment/backends/sql.py
@@ -0,0 +1,751 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012-13 OpenStack LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from keystone import assignment
+from keystone import clean
+from keystone.common import dependency
+from keystone.common import sql
+from keystone.common.sql import migration
+from keystone import exception
+
+
+@dependency.requires('identity_api')
+class Assignment(sql.Base, assignment.Driver):
+
+ # Internal interface to manage the database
+ def db_sync(self, version=None):
+ migration.db_sync(version=version)
+
+ def _get_project(self, session, project_id):
+ project_ref = session.query(Project).get(project_id)
+ if project_ref is None:
+ raise exception.ProjectNotFound(project_id=project_id)
+ return project_ref
+
+ def get_project(self, tenant_id):
+ session = self.get_session()
+ return self._get_project(session, tenant_id).to_dict()
+
+ def get_project_by_name(self, tenant_name, domain_id):
+ session = self.get_session()
+ query = session.query(Project)
+ query = query.filter_by(name=tenant_name)
+ query = query.filter_by(domain_id=domain_id)
+ try:
+ project_ref = query.one()
+ except sql.NotFound:
+ raise exception.ProjectNotFound(project_id=tenant_name)
+ return project_ref.to_dict()
+
+ def get_project_user_ids(self, tenant_id):
+ session = self.get_session()
+ self.get_project(tenant_id)
+ query = session.query(UserProjectGrant)
+ query = query.filter(UserProjectGrant.project_id ==
+ tenant_id)
+ project_refs = query.all()
+ return [project_ref.user_id for project_ref in project_refs]
+
+ def get_project_users(self, tenant_id):
+ self.get_session()
+ self.get_project(tenant_id)
+ user_refs = []
+ #TODO(ayoung): Move to controller or manager
+ for user_id in self.get_project_user_ids(tenant_id):
+ user_ref = self.identity_api.get_user(user_id)
+ user_refs.append(user_ref)
+ return user_refs
+
+ def _get_metadata(self, user_id=None, tenant_id=None,
+ domain_id=None, group_id=None):
+ session = self.get_session()
+
+ if user_id:
+ if tenant_id:
+ q = session.query(UserProjectGrant)
+ q = q.filter_by(project_id=tenant_id)
+ elif domain_id:
+ q = session.query(UserDomainGrant)
+ q = q.filter_by(domain_id=domain_id)
+ q = q.filter_by(user_id=user_id)
+ elif group_id:
+ if tenant_id:
+ q = session.query(GroupProjectGrant)
+ q = q.filter_by(project_id=tenant_id)
+ elif domain_id:
+ q = session.query(GroupDomainGrant)
+ q = q.filter_by(domain_id=domain_id)
+ q = q.filter_by(group_id=group_id)
+ try:
+ return q.one().data
+ except sql.NotFound:
+ raise exception.MetadataNotFound()
+
+ def create_grant(self, role_id, user_id=None, group_id=None,
+ domain_id=None, project_id=None,
+ inherited_to_projects=False):
+ if user_id:
+ self.identity_api.get_user(user_id)
+ if group_id:
+ self.identity_api.get_group(group_id)
+
+ session = self.get_session()
+ self._get_role(session, role_id)
+
+ if domain_id:
+ self._get_domain(session, domain_id)
+ if project_id:
+ self._get_project(session, project_id)
+
+ if project_id and inherited_to_projects:
+ msg = _('Inherited roles can only be assigned to domains')
+ raise exception.Conflict(type='role grant', details=msg)
+
+ try:
+ metadata_ref = self._get_metadata(user_id, project_id,
+ domain_id, group_id)
+ is_new = False
+ except exception.MetadataNotFound:
+ metadata_ref = {}
+ is_new = True
+
+ metadata_ref['roles'] = self._add_role_to_role_dicts(
+ role_id, inherited_to_projects, metadata_ref.get('roles', []))
+
+ if is_new:
+ self._create_metadata(user_id, project_id, metadata_ref,
+ domain_id, group_id)
+ else:
+ self._update_metadata(user_id, project_id, metadata_ref,
+ domain_id, group_id)
+
+ def list_grants(self, user_id=None, group_id=None,
+ domain_id=None, project_id=None,
+ inherited_to_projects=False):
+ if user_id:
+ self.identity_api.get_user(user_id)
+ if group_id:
+ self.identity_api.get_group(group_id)
+ session = self.get_session()
+ if domain_id:
+ self._get_domain(session, domain_id)
+ if project_id:
+ self._get_project(session, project_id)
+
+ try:
+ metadata_ref = self._get_metadata(user_id, project_id,
+ domain_id, group_id)
+ except exception.MetadataNotFound:
+ metadata_ref = {}
+
+ return [self.get_role(x) for x in
+ self._roles_from_role_dicts(metadata_ref.get('roles', []),
+ inherited_to_projects)]
+
+ def get_grant(self, role_id, user_id=None, group_id=None,
+ domain_id=None, project_id=None,
+ inherited_to_projects=False):
+ if user_id:
+ self.identity_api.get_user(user_id)
+ if group_id:
+ self.identity_api.get_group(group_id)
+
+ session = self.get_session()
+ role_ref = self._get_role(session, role_id)
+
+ if domain_id:
+ self._get_domain(session, domain_id)
+ if project_id:
+ self._get_project(session, project_id)
+
+ try:
+ metadata_ref = self._get_metadata(user_id, project_id,
+ domain_id, group_id)
+ except exception.MetadataNotFound:
+ metadata_ref = {}
+ role_ids = set(self._roles_from_role_dicts(
+ metadata_ref.get('roles', []), inherited_to_projects))
+ if role_id not in role_ids:
+ raise exception.RoleNotFound(role_id=role_id)
+ return role_ref.to_dict()
+
+ def delete_grant(self, role_id, user_id=None, group_id=None,
+ domain_id=None, project_id=None,
+ inherited_to_projects=False):
+ if user_id:
+ self.identity_api.get_user(user_id)
+ if group_id:
+ self.identity_api.get_group(group_id)
+
+ session = self.get_session()
+ self._get_role(session, role_id)
+
+ if domain_id:
+ self._get_domain(session, domain_id)
+ if project_id:
+ self._get_project(session, project_id)
+
+ try:
+ metadata_ref = self._get_metadata(user_id, project_id,
+ domain_id, group_id)
+ is_new = False
+ except exception.MetadataNotFound:
+ metadata_ref = {}
+ is_new = True
+
+ try:
+ metadata_ref['roles'] = self._remove_role_from_role_dicts(
+ role_id, inherited_to_projects, metadata_ref.get('roles', []))
+ except KeyError:
+ raise exception.RoleNotFound(role_id=role_id)
+
+ if is_new:
+ # TODO(henry-nash) It seems odd that you would create a new
+ # entry in response to trying to delete a role that was not
+ # assigned. Although benign, this should probably be removed.
+ self._create_metadata(user_id, project_id, metadata_ref,
+ domain_id, group_id)
+ else:
+ self._update_metadata(user_id, project_id, metadata_ref,
+ domain_id, group_id)
+
+ def list_projects(self, domain_id=None):
+ session = self.get_session()
+ if domain_id:
+ self._get_domain(session, domain_id)
+
+ query = session.query(Project)
+ if domain_id:
+ query = query.filter_by(domain_id=domain_id)
+ project_refs = query.all()
+ return [project_ref.to_dict() for project_ref in project_refs]
+
+ def get_projects_for_user(self, user_id):
+
+ # FIXME(henry-nash) The following should take into account
+ # both group and inherited roles. In fact, I don't see why this
+ # call can't be handled at the controller level like we do
+ # with 'get_roles_for_user_and_project()'. Further, this
+ # call seems essentially the same as 'list_user_projects()'
+ # later in this driver. Both should be removed.
+
+ self.identity_api.get_user(user_id)
+ session = self.get_session()
+ query = session.query(UserProjectGrant)
+ query = query.filter_by(user_id=user_id)
+ membership_refs = query.all()
+ return [x.project_id for x in membership_refs]
+
+ def add_role_to_user_and_project(self, user_id, tenant_id, role_id):
+ self.identity_api.get_user(user_id)
+ session = self.get_session()
+ self._get_project(session, tenant_id)
+ self._get_role(session, role_id)
+ try:
+ metadata_ref = self._get_metadata(user_id, tenant_id)
+ is_new = False
+ except exception.MetadataNotFound:
+ metadata_ref = {}
+ is_new = True
+
+ try:
+ metadata_ref['roles'] = self._add_role_to_role_dicts(
+ role_id, False, metadata_ref.get('roles', []),
+ allow_existing=False)
+ except KeyError:
+ msg = ('User %s already has role %s in tenant %s'
+ % (user_id, role_id, tenant_id))
+ raise exception.Conflict(type='role grant', details=msg)
+
+ if is_new:
+ self._create_metadata(user_id, tenant_id, metadata_ref)
+ else:
+ self._update_metadata(user_id, tenant_id, metadata_ref)
+
+ def remove_role_from_user_and_project(self, user_id, tenant_id, role_id):
+ try:
+ metadata_ref = self._get_metadata(user_id, tenant_id)
+ try:
+ metadata_ref['roles'] = self._remove_role_from_role_dicts(
+ role_id, False, metadata_ref.get('roles', []))
+ except KeyError:
+ raise exception.RoleNotFound(message=_(
+ 'Cannot remove role that has not been granted, %s') %
+ role_id)
+
+ if len(metadata_ref['roles']):
+ self._update_metadata(user_id, tenant_id, metadata_ref)
+ else:
+ session = self.get_session()
+ q = session.query(UserProjectGrant)
+ q = q.filter_by(user_id=user_id)
+ q = q.filter_by(project_id=tenant_id)
+ q.delete()
+ except exception.MetadataNotFound:
+ msg = 'Cannot remove role that has not been granted, %s' % role_id
+ raise exception.RoleNotFound(message=msg)
+
+ def list_role_assignments(self):
+
+ # TODO(henry-nash): The current implementation is really simulating
+ # us having a common role assignment table, rather than having the
+ # four different grant tables we have today. When we move to role
+ # assignment as a first class entity, we should create the single
+ # assignment table, simplifying the logic of this (and many other)
+ # functions.
+
+ session = self.get_session()
+ assignment_list = []
+ refs = session.query(UserDomainGrant).all()
+ for x in refs:
+ for r in self._roles_from_role_dicts(
+ x.data.get('roles', {}), False):
+ assignment_list.append({'user_id': x.user_id,
+ 'domain_id': x.domain_id,
+ 'role_id': r})
+ for r in self._roles_from_role_dicts(
+ x.data.get('roles', {}), True):
+ assignment_list.append({'user_id': x.user_id,
+ 'domain_id': x.domain_id,
+ 'role_id': r,
+ 'inherited_to_projects': True})
+ refs = session.query(UserProjectGrant).all()
+ for x in refs:
+ for r in self._roles_from_role_dicts(
+ x.data.get('roles', {}), False):
+ assignment_list.append({'user_id': x.user_id,
+ 'project_id': x.project_id,
+ 'role_id': r})
+ refs = session.query(GroupDomainGrant).all()
+ for x in refs:
+ for r in self._roles_from_role_dicts(
+ x.data.get('roles', {}), False):
+ assignment_list.append({'group_id': x.group_id,
+ 'domain_id': x.domain_id,
+ 'role_id': r})
+ for r in self._roles_from_role_dicts(
+ x.data.get('roles', {}), True):
+ assignment_list.append({'group_id': x.group_id,
+ 'domain_id': x.domain_id,
+ 'role_id': r,
+ 'inherited_to_projects': True})
+ refs = session.query(GroupProjectGrant).all()
+ for x in refs:
+ for r in self._roles_from_role_dicts(
+ x.data.get('roles', {}), False):
+ assignment_list.append({'group_id': x.group_id,
+ 'project_id': x.project_id,
+ 'role_id': r})
+ return assignment_list
+
+ # CRUD
+ @sql.handle_conflicts(type='project')
+ def create_project(self, tenant_id, tenant):
+ tenant['name'] = clean.project_name(tenant['name'])
+ session = self.get_session()
+ with session.begin():
+ tenant_ref = Project.from_dict(tenant)
+ session.add(tenant_ref)
+ session.flush()
+ return tenant_ref.to_dict()
+
+ @sql.handle_conflicts(type='project')
+ def update_project(self, tenant_id, tenant):
+ session = self.get_session()
+
+ if 'name' in tenant:
+ tenant['name'] = clean.project_name(tenant['name'])
+
+ with session.begin():
+ tenant_ref = self._get_project(session, tenant_id)
+ old_project_dict = tenant_ref.to_dict()
+ for k in tenant:
+ old_project_dict[k] = tenant[k]
+ new_project = Project.from_dict(old_project_dict)
+ for attr in Project.attributes:
+ if attr != 'id':
+ setattr(tenant_ref, attr, getattr(new_project, attr))
+ tenant_ref.extra = new_project.extra
+ session.flush()
+ return tenant_ref.to_dict(include_extra_dict=True)
+
+ @sql.handle_conflicts(type='project')
+ def delete_project(self, tenant_id):
+ session = self.get_session()
+
+ with session.begin():
+ tenant_ref = self._get_project(session, tenant_id)
+
+ q = session.query(UserProjectGrant)
+ q = q.filter_by(project_id=tenant_id)
+ q.delete(False)
+
+ q = session.query(UserProjectGrant)
+ q = q.filter_by(project_id=tenant_id)
+ q.delete(False)
+
+ q = session.query(GroupProjectGrant)
+ q = q.filter_by(project_id=tenant_id)
+ q.delete(False)
+
+ session.delete(tenant_ref)
+ session.flush()
+
+ @sql.handle_conflicts(type='metadata')
+ def _create_metadata(self, user_id, tenant_id, metadata,
+ domain_id=None, group_id=None):
+ session = self.get_session()
+ with session.begin():
+ if user_id:
+ if tenant_id:
+ session.add(UserProjectGrant
+ (user_id=user_id,
+ project_id=tenant_id,
+ data=metadata))
+ elif domain_id:
+ session.add(UserDomainGrant
+ (user_id=user_id,
+ domain_id=domain_id,
+ data=metadata))
+ elif group_id:
+ if tenant_id:
+ session.add(GroupProjectGrant
+ (group_id=group_id,
+ project_id=tenant_id,
+ data=metadata))
+ elif domain_id:
+ session.add(GroupDomainGrant
+ (group_id=group_id,
+ domain_id=domain_id,
+ data=metadata))
+ session.flush()
+ return metadata
+
+ @sql.handle_conflicts(type='metadata')
+ def _update_metadata(self, user_id, tenant_id, metadata,
+ domain_id=None, group_id=None):
+ session = self.get_session()
+ with session.begin():
+ if user_id:
+ if tenant_id:
+ q = session.query(UserProjectGrant)
+ q = q.filter_by(user_id=user_id)
+ q = q.filter_by(project_id=tenant_id)
+ elif domain_id:
+ q = session.query(UserDomainGrant)
+ q = q.filter_by(user_id=user_id)
+ q = q.filter_by(domain_id=domain_id)
+ elif group_id:
+ if tenant_id:
+ q = session.query(GroupProjectGrant)
+ q = q.filter_by(group_id=group_id)
+ q = q.filter_by(project_id=tenant_id)
+ elif domain_id:
+ q = session.query(GroupDomainGrant)
+ q = q.filter_by(group_id=group_id)
+ q = q.filter_by(domain_id=domain_id)
+ metadata_ref = q.first()
+ data = metadata_ref.data.copy()
+ data.update(metadata)
+ metadata_ref.data = data
+ session.flush()
+ return metadata_ref
+
+ # domain crud
+
+ @sql.handle_conflicts(type='domain')
+ def create_domain(self, domain_id, domain):
+ session = self.get_session()
+ with session.begin():
+ ref = Domain.from_dict(domain)
+ session.add(ref)
+ session.flush()
+ return ref.to_dict()
+
+ def list_domains(self):
+ session = self.get_session()
+ refs = session.query(Domain).all()
+ return [ref.to_dict() for ref in refs]
+
+ def _get_domain(self, session, domain_id):
+ ref = session.query(Domain).get(domain_id)
+ if ref is None:
+ raise exception.DomainNotFound(domain_id=domain_id)
+ return ref
+
+ def get_domain(self, domain_id):
+ session = self.get_session()
+ return self._get_domain(session, domain_id).to_dict()
+
+ def get_domain_by_name(self, domain_name):
+ session = self.get_session()
+ try:
+ ref = (session.query(Domain).
+ filter_by(name=domain_name).one())
+ except sql.NotFound:
+ raise exception.DomainNotFound(domain_id=domain_name)
+ return ref.to_dict()
+
+ @sql.handle_conflicts(type='domain')
+ def update_domain(self, domain_id, domain):
+ session = self.get_session()
+ with session.begin():
+ ref = self._get_domain(session, domain_id)
+ old_dict = ref.to_dict()
+ for k in domain:
+ old_dict[k] = domain[k]
+ new_domain = Domain.from_dict(old_dict)
+ for attr in Domain.attributes:
+ if attr != 'id':
+ setattr(ref, attr, getattr(new_domain, attr))
+ ref.extra = new_domain.extra
+ session.flush()
+ return ref.to_dict()
+
+ def delete_domain(self, domain_id):
+ session = self.get_session()
+ with session.begin():
+ ref = self._get_domain(session, domain_id)
+ session.delete(ref)
+ session.flush()
+
+ def list_user_projects(self, user_id):
+
+ # FIXME(henry-nash) The following should take into account
+ # both group and inherited roles. In fact, I don't see why this
+ # call can't be handled at the controller level like we do
+ # with 'get_roles_for_user_and_project()'. Further, this
+ # call seems essentially the same as 'get_projects_for_user()'
+ # earlier in this driver. Both should be removed.
+
+ session = self.get_session()
+ user = self.identity_api.get_user(user_id)
+ metadata_refs = session\
+ .query(UserProjectGrant)\
+ .filter_by(user_id=user_id)
+ project_ids = set([x.project_id for x in metadata_refs
+ if x.data.get('roles')])
+ if user.get('project_id'):
+ project_ids.add(user['project_id'])
+
+ # FIXME(dolph): this should be removed with proper migrations
+ if user.get('tenant_id'):
+ project_ids.add(user['tenant_id'])
+
+ return [self.get_project(x) for x in project_ids]
+
+ # role crud
+
+ @sql.handle_conflicts(type='role')
+ def create_role(self, role_id, role):
+ session = self.get_session()
+ with session.begin():
+ ref = Role.from_dict(role)
+ session.add(ref)
+ session.flush()
+ return ref.to_dict()
+
+ def list_roles(self):
+ session = self.get_session()
+ refs = session.query(Role).all()
+ return [ref.to_dict() for ref in refs]
+
+ def _get_role(self, session, role_id):
+ ref = session.query(Role).get(role_id)
+ if ref is None:
+ raise exception.RoleNotFound(role_id=role_id)
+ return ref
+
+ def get_role(self, role_id):
+ session = self.get_session()
+ return self._get_role(session, role_id).to_dict()
+
+ @sql.handle_conflicts(type='role')
+ def update_role(self, role_id, role):
+ session = self.get_session()
+ with session.begin():
+ ref = self._get_role(session, role_id)
+ old_dict = ref.to_dict()
+ for k in role:
+ old_dict[k] = role[k]
+ new_role = Role.from_dict(old_dict)
+ for attr in Role.attributes:
+ if attr != 'id':
+ setattr(ref, attr, getattr(new_role, attr))
+ ref.extra = new_role.extra
+ session.flush()
+ return ref.to_dict()
+
+ def delete_role(self, role_id):
+ session = self.get_session()
+
+ with session.begin():
+ ref = self._get_role(session, role_id)
+ for metadata_ref in session.query(UserProjectGrant):
+ try:
+ self.delete_grant(role_id, user_id=metadata_ref.user_id,
+ project_id=metadata_ref.project_id)
+ except exception.RoleNotFound:
+ pass
+ for metadata_ref in session.query(UserDomainGrant):
+ try:
+ self.delete_grant(role_id, user_id=metadata_ref.user_id,
+ domain_id=metadata_ref.domain_id)
+ except exception.RoleNotFound:
+ pass
+ for metadata_ref in session.query(GroupProjectGrant):
+ try:
+ self.delete_grant(role_id, group_id=metadata_ref.group_id,
+ project_id=metadata_ref.project_id)
+ except exception.RoleNotFound:
+ pass
+ for metadata_ref in session.query(GroupDomainGrant):
+ try:
+ self.delete_grant(role_id, group_id=metadata_ref.group_id,
+ domain_id=metadata_ref.domain_id)
+ except exception.RoleNotFound:
+ pass
+
+ session.delete(ref)
+ session.flush()
+
+ def delete_user(self, user_id):
+ session = self.get_session()
+
+ with session.begin():
+ q = session.query(UserProjectGrant)
+ q = q.filter_by(user_id=user_id)
+ q.delete(False)
+
+ q = session.query(UserDomainGrant)
+ q = q.filter_by(user_id=user_id)
+ q.delete(False)
+
+ session.flush()
+
+ def delete_group(self, group_id):
+ session = self.get_session()
+
+ with session.begin():
+
+ q = session.query(GroupProjectGrant)
+ q = q.filter_by(group_id=group_id)
+ q.delete(False)
+
+ q = session.query(GroupDomainGrant)
+ q = q.filter_by(group_id=group_id)
+ q.delete(False)
+
+ session.flush()
+
+
+class Domain(sql.ModelBase, sql.DictBase):
+ __tablename__ = 'domain'
+ attributes = ['id', 'name', 'enabled']
+ id = sql.Column(sql.String(64), primary_key=True)
+ name = sql.Column(sql.String(64), nullable=False)
+ enabled = sql.Column(sql.Boolean, default=True, nullable=False)
+ extra = sql.Column(sql.JsonBlob())
+ __table_args__ = (sql.UniqueConstraint('name'), {})
+
+
+class Project(sql.ModelBase, sql.DictBase):
+ __tablename__ = 'project'
+ attributes = ['id', 'name', 'domain_id', 'description', 'enabled']
+ id = sql.Column(sql.String(64), primary_key=True)
+ name = sql.Column(sql.String(64), nullable=False)
+ domain_id = sql.Column(sql.String(64), sql.ForeignKey('domain.id'),
+ nullable=False)
+ description = sql.Column(sql.Text())
+ enabled = sql.Column(sql.Boolean)
+ extra = sql.Column(sql.JsonBlob())
+ # Unique constraint across two columns to create the separation
+ # rather than just only 'name' being unique
+ __table_args__ = (sql.UniqueConstraint('domain_id', 'name'), {})
+
+
+class Role(sql.ModelBase, sql.DictBase):
+ __tablename__ = 'role'
+ attributes = ['id', 'name']
+ id = sql.Column(sql.String(64), primary_key=True)
+ name = sql.Column(sql.String(255), nullable=False)
+ extra = sql.Column(sql.JsonBlob())
+ __table_args__ = (sql.UniqueConstraint('name'), {})
+
+
+class BaseGrant(sql.DictBase):
+ """Base Grant class.
+
+ There are four grant tables in the current implementation, one for
+ each type of grant:
+
+ - User for Project
+ - User for Domain
+ - Group for Project
+ - Group for Domain
+
+ Each is a table with the two attributes above as a combined primary key,
+ with the data field holding all roles for that combination. The data
+ field is a list of dicts. For regular role assignments each dict in
+ the list of of the form:
+
+ {'id': role_id}
+
+ If the OS-INHERIT extension is enabled and the role on a domain is an
+ inherited role, the dict will be of the form:
+
+ {'id': role_id, 'inherited_to': 'projects'}
+
+ """
+ def to_dict(self):
+ """Override parent to_dict() method with a simpler implementation.
+
+ Grant tables don't have non-indexed 'extra' attributes, so the
+ parent implementation is not applicable.
+ """
+ return dict(self.iteritems())
+
+
+class UserProjectGrant(sql.ModelBase, BaseGrant):
+ __tablename__ = 'user_project_metadata'
+ user_id = sql.Column(sql.String(64), primary_key=True)
+ project_id = sql.Column(sql.String(64), sql.ForeignKey('project.id'),
+ primary_key=True)
+ data = sql.Column(sql.JsonBlob())
+
+
+class UserDomainGrant(sql.ModelBase, BaseGrant):
+ __tablename__ = 'user_domain_metadata'
+ user_id = sql.Column(sql.String(64), primary_key=True)
+ domain_id = sql.Column(sql.String(64), sql.ForeignKey('domain.id'),
+ primary_key=True)
+ data = sql.Column(sql.JsonBlob())
+
+
+class GroupProjectGrant(sql.ModelBase, BaseGrant):
+ __tablename__ = 'group_project_metadata'
+ group_id = sql.Column(sql.String(64), primary_key=True)
+ project_id = sql.Column(sql.String(64), sql.ForeignKey('project.id'),
+ primary_key=True)
+ data = sql.Column(sql.JsonBlob())
+
+
+class GroupDomainGrant(sql.ModelBase, BaseGrant):
+ __tablename__ = 'group_domain_metadata'
+ group_id = sql.Column(sql.String(64), primary_key=True)
+ domain_id = sql.Column(sql.String(64), sql.ForeignKey('domain.id'),
+ primary_key=True)
+ data = sql.Column(sql.JsonBlob())
diff --git a/keystone/assignment/core.py b/keystone/assignment/core.py
new file mode 100644
index 00000000..64edb3fa
--- /dev/null
+++ b/keystone/assignment/core.py
@@ -0,0 +1,548 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+"""Main entry point into the assignment service."""
+
+from keystone.common import dependency
+from keystone.common import logging
+from keystone.common import manager
+from keystone import config
+from keystone import exception
+
+
+CONF = config.CONF
+LOG = logging.getLogger(__name__)
+
+DEFAULT_DOMAIN = {'description':
+ (u'Owns users and tenants (i.e. projects)'
+ ' available on Identity API v2.'),
+ 'enabled': True,
+ 'id': CONF.identity.default_domain_id,
+ 'name': u'Default'}
+
+
+@dependency.provider('assignment_api')
+@dependency.requires('identity_api')
+class Manager(manager.Manager):
+ """Default pivot point for the Assignment backend.
+
+ See :mod:`keystone.common.manager.Manager` for more details on how this
+ dynamically calls the backend.
+ assignment.Manager() and identity.Manager() have a circular dependency.
+ The late import works around this. THe if block prevents creation of the
+ api object by both managers.
+ """
+
+ def __init__(self):
+ assignment_driver = CONF.assignment.driver
+
+ if assignment_driver is None:
+ identity_driver = dependency.REGISTRY['identity_api'].driver
+ assignment_driver = identity_driver.default_assignment_driver()
+
+ super(Manager, self).__init__(assignment_driver)
+
+ def get_roles_for_user_and_project(self, user_id, tenant_id):
+ """Get the roles associated with a user within given project.
+
+ This includes roles directly assigned to the user on the
+ project, as well as those by virtue of group membership. If
+ the OS-INHERIT extension is enabled, then this will also
+ include roles inherited from the domain.
+
+ :returns: a list of role ids.
+ :raises: keystone.exception.UserNotFound,
+ keystone.exception.ProjectNotFound
+
+ """
+ def _get_group_project_roles(user_id, project_ref):
+ role_list = []
+ group_refs = (self.identity_api.list_groups_for_user
+ (user_id=user_id))
+ for x in group_refs:
+ try:
+ metadata_ref = self._get_metadata(
+ group_id=x['id'], tenant_id=project_ref['id'])
+ role_list += self._roles_from_role_dicts(
+ metadata_ref.get('roles', {}), False)
+ except exception.MetadataNotFound:
+ # no group grant, skip
+ pass
+
+ if CONF.os_inherit.enabled:
+ # Now get any inherited group roles for the owning domain
+ try:
+ metadata_ref = self._get_metadata(
+ group_id=x['id'],
+ domain_id=project_ref['domain_id'])
+ role_list += self._roles_from_role_dicts(
+ metadata_ref.get('roles', {}), True)
+ except (exception.MetadataNotFound,
+ exception.NotImplemented):
+ pass
+
+ return role_list
+
+ def _get_user_project_roles(user_id, project_ref):
+ role_list = []
+ try:
+ metadata_ref = self._get_metadata(user_id=user_id,
+ tenant_id=project_ref['id'])
+ role_list = self._roles_from_role_dicts(
+ metadata_ref.get('roles', {}), False)
+ except exception.MetadataNotFound:
+ pass
+
+ if CONF.os_inherit.enabled:
+ # Now get any inherited roles for the owning domain
+ try:
+ metadata_ref = self._get_metadata(
+ user_id=user_id, domain_id=project_ref['domain_id'])
+ role_list += self._roles_from_role_dicts(
+ metadata_ref.get('roles', {}), True)
+ except (exception.MetadataNotFound, exception.NotImplemented):
+ pass
+
+ return role_list
+
+ self.identity_api.get_user(user_id)
+ project_ref = self.get_project(tenant_id)
+ user_role_list = _get_user_project_roles(user_id, project_ref)
+ group_role_list = _get_group_project_roles(user_id, project_ref)
+ # Use set() to process the list to remove any duplicates
+ return list(set(user_role_list + group_role_list))
+
+ def get_roles_for_user_and_domain(self, user_id, domain_id):
+ """Get the roles associated with a user within given domain.
+
+ :returns: a list of role ids.
+ :raises: keystone.exception.UserNotFound,
+ keystone.exception.DomainNotFound
+
+ """
+
+ def _get_group_domain_roles(user_id, domain_id):
+ role_list = []
+ group_refs = (self.identity_api.
+ list_groups_for_user(user_id=user_id))
+ for x in group_refs:
+ try:
+ metadata_ref = self._get_metadata(group_id=x['id'],
+ domain_id=domain_id)
+ role_list += self._roles_from_role_dicts(
+ metadata_ref.get('roles', {}), False)
+ except (exception.MetadataNotFound, exception.NotImplemented):
+ # MetadataNotFound implies no group grant, so skip.
+ # Ignore NotImplemented since not all backends support
+ # domains.
+ pass
+ return role_list
+
+ def _get_user_domain_roles(user_id, domain_id):
+ metadata_ref = {}
+ try:
+ metadata_ref = self._get_metadata(user_id=user_id,
+ domain_id=domain_id)
+ except (exception.MetadataNotFound, exception.NotImplemented):
+ # MetadataNotFound implies no user grants.
+ # Ignore NotImplemented since not all backends support
+ # domains
+ pass
+ return self._roles_from_role_dicts(
+ metadata_ref.get('roles', {}), False)
+
+ self.identity_api.get_user(user_id)
+ self.get_domain(domain_id)
+ user_role_list = _get_user_domain_roles(user_id, domain_id)
+ group_role_list = _get_group_domain_roles(user_id, domain_id)
+ # Use set() to process the list to remove any duplicates
+ return list(set(user_role_list + group_role_list))
+
+ def add_user_to_project(self, tenant_id, user_id):
+ """Add user to a tenant by creating a default role relationship.
+
+ :raises: keystone.exception.ProjectNotFound,
+ keystone.exception.UserNotFound
+
+ """
+ self.driver.add_role_to_user_and_project(user_id,
+ tenant_id,
+ config.CONF.member_role_id)
+
+ def remove_user_from_project(self, tenant_id, user_id):
+ """Remove user from a tenant
+
+ :raises: keystone.exception.ProjectNotFound,
+ keystone.exception.UserNotFound
+
+ """
+ roles = self.get_roles_for_user_and_project(user_id, tenant_id)
+ if not roles:
+ raise exception.NotFound(tenant_id)
+ for role_id in roles:
+ self.remove_role_from_user_and_project(user_id, tenant_id, role_id)
+
+
+class Driver(object):
+
+ def _role_to_dict(self, role_id, inherited):
+ role_dict = {'id': role_id}
+ if inherited:
+ role_dict['inherited_to'] = 'projects'
+ return role_dict
+
+ def _roles_from_role_dicts(self, dict_list, inherited):
+ role_list = []
+ for d in dict_list:
+ if ((not d.get('inherited_to') and not inherited) or
+ (d.get('inherited_to') == 'projects' and inherited)):
+ role_list.append(d['id'])
+ return role_list
+
+ def _add_role_to_role_dicts(self, role_id, inherited, dict_list,
+ allow_existing=True):
+ # There is a difference in error semantics when trying to
+ # assign a role that already exists between the coded v2 and v3
+ # API calls. v2 will error if the assignment already exists,
+ # while v3 is silent. Setting the 'allow_existing' parameter
+ # appropriately lets this call be used for both.
+ role_set = set([frozenset(r.items()) for r in dict_list])
+ key = frozenset(self._role_to_dict(role_id, inherited).items())
+ if not allow_existing and key in role_set:
+ raise KeyError
+ role_set.add(key)
+ return [dict(r) for r in role_set]
+
+ def _remove_role_from_role_dicts(self, role_id, inherited, dict_list):
+ role_set = set([frozenset(r.items()) for r in dict_list])
+ role_set.remove(frozenset(self._role_to_dict(role_id,
+ inherited).items()))
+ return [dict(r) for r in role_set]
+
+ def get_project_by_name(self, tenant_name, domain_id):
+ """Get a tenant by name.
+
+ :returns: tenant_ref
+ :raises: keystone.exception.ProjectNotFound
+
+ """
+ raise exception.NotImplemented()
+
+ def get_project_users(self, tenant_id):
+ """Lists all users with a relationship to the specified project.
+
+ :returns: a list of user_refs or an empty set.
+ :raises: keystone.exception.ProjectNotFound
+
+ """
+ raise exception.NotImplemented()
+
+ def get_projects_for_user(self, user_id):
+ """Get the tenants associated with a given user.
+
+ :returns: a list of tenant_id's.
+ :raises: keystone.exception.UserNotFound
+
+ """
+ raise exception.NotImplemented()
+
+ def add_role_to_user_and_project(self, user_id, tenant_id, role_id):
+ """Add a role to a user within given tenant.
+
+ :raises: keystone.exception.UserNotFound,
+ keystone.exception.ProjectNotFound,
+ keystone.exception.RoleNotFound
+ """
+ raise exception.NotImplemented()
+
+ def remove_role_from_user_and_project(self, user_id, tenant_id, role_id):
+ """Remove a role from a user within given tenant.
+
+ :raises: keystone.exception.UserNotFound,
+ keystone.exception.ProjectNotFound,
+ keystone.exception.RoleNotFound
+
+ """
+ raise exception.NotImplemented()
+
+ # assignment/grant crud
+
+ def create_grant(self, role_id, user_id=None, group_id=None,
+ domain_id=None, project_id=None,
+ inherited_to_projects=False):
+ """Creates a new assignment/grant.
+
+ If the assignment is to a domain, then optionally it may be
+ specified as inherited to owned projects (this requires
+ the OS-INHERIT extension to be enabled).
+
+ :raises: keystone.exception.UserNotFound,
+ keystone.exception.GroupNotFound,
+ keystone.exception.ProjectNotFound,
+ keystone.exception.DomainNotFound,
+ keystone.exception.ProjectNotFound,
+ keystone.exception.RoleNotFound
+
+ """
+ raise exception.NotImplemented()
+
+ def list_grants(self, user_id=None, group_id=None,
+ domain_id=None, project_id=None,
+ inherited_to_projects=False):
+ """Lists assignments/grants.
+
+ :raises: keystone.exception.UserNotFound,
+ keystone.exception.GroupNotFound,
+ keystone.exception.ProjectNotFound,
+ keystone.exception.DomainNotFound,
+ keystone.exception.ProjectNotFound,
+ keystone.exception.RoleNotFound
+
+ """
+ raise exception.NotImplemented()
+
+ def get_grant(self, role_id, user_id=None, group_id=None,
+ domain_id=None, project_id=None,
+ inherited_to_projects=False):
+ """Lists assignments/grants.
+
+ :raises: keystone.exception.UserNotFound,
+ keystone.exception.GroupNotFound,
+ keystone.exception.ProjectNotFound,
+ keystone.exception.DomainNotFound,
+ keystone.exception.ProjectNotFound,
+ keystone.exception.RoleNotFound
+
+ """
+ raise exception.NotImplemented()
+
+ def delete_grant(self, role_id, user_id=None, group_id=None,
+ domain_id=None, project_id=None,
+ inherited_to_projects=False):
+ """Lists assignments/grants.
+
+ :raises: keystone.exception.UserNotFound,
+ keystone.exception.GroupNotFound,
+ keystone.exception.ProjectNotFound,
+ keystone.exception.DomainNotFound,
+ keystone.exception.ProjectNotFound,
+ keystone.exception.RoleNotFound
+
+ """
+ raise exception.NotImplemented()
+
+ def list_role_assignments(self):
+
+ raise exception.NotImplemented()
+
+ # domain crud
+ def create_domain(self, domain_id, domain):
+ """Creates a new domain.
+
+ :raises: keystone.exception.Conflict
+
+ """
+ raise exception.NotImplemented()
+
+ def list_domains(self):
+ """List all domains in the system.
+
+ :returns: a list of domain_refs or an empty list.
+
+ """
+ raise exception.NotImplemented()
+
+ def get_domain(self, domain_id):
+ """Get a domain by ID.
+
+ :returns: domain_ref
+ :raises: keystone.exception.DomainNotFound
+
+ """
+ raise exception.NotImplemented()
+
+ def get_domain_by_name(self, domain_name):
+ """Get a domain by name.
+
+ :returns: domain_ref
+ :raises: keystone.exception.DomainNotFound
+
+ """
+ raise exception.NotImplemented()
+
+ def update_domain(self, domain_id, domain):
+ """Updates an existing domain.
+
+ :raises: keystone.exception.DomainNotFound,
+ keystone.exception.Conflict
+
+ """
+ raise exception.NotImplemented()
+
+ def delete_domain(self, domain_id):
+ """Deletes an existing domain.
+
+ :raises: keystone.exception.DomainNotFound
+
+ """
+ raise exception.NotImplemented()
+
+ # project crud
+ def create_project(self, project_id, project):
+ """Creates a new project.
+
+ :raises: keystone.exception.Conflict
+
+ """
+ raise exception.NotImplemented()
+
+ def list_projects(self, domain_id=None):
+ """List all projects in the system.
+
+ :returns: a list of project_refs or an empty list.
+
+ """
+ raise exception.NotImplemented()
+
+ def list_user_projects(self, user_id):
+ """List all projects associated with a given user.
+
+ :returns: a list of project_refs or an empty list.
+
+ """
+ raise exception.NotImplemented()
+
+ def get_project(self, project_id):
+ """Get a project by ID.
+
+ :returns: project_ref
+ :raises: keystone.exception.ProjectNotFound
+
+ """
+ raise exception.NotImplemented()
+
+ def update_project(self, project_id, project):
+ """Updates an existing project.
+
+ :raises: keystone.exception.ProjectNotFound,
+ keystone.exception.Conflict
+
+ """
+ raise exception.NotImplemented()
+
+ def delete_project(self, project_id):
+ """Deletes an existing project.
+
+ :raises: keystone.exception.ProjectNotFound
+
+ """
+ raise exception.NotImplemented()
+
+ """Interface description for an assignment driver."""
+ # role crud
+
+ def create_role(self, role_id, role):
+ """Creates a new role.
+
+ :raises: keystone.exception.Conflict
+
+ """
+ raise exception.NotImplemented()
+
+ def list_roles(self):
+ """List all roles in the system.
+
+ :returns: a list of role_refs or an empty list.
+
+ """
+ raise exception.NotImplemented()
+
+ def get_role(self, role_id):
+ """Get a role by ID.
+
+ :returns: role_ref
+ :raises: keystone.exception.RoleNotFound
+
+ """
+ raise exception.NotImplemented()
+
+ def update_role(self, role_id, role):
+ """Updates an existing role.
+
+ :raises: keystone.exception.RoleNotFound,
+ keystone.exception.Conflict
+
+ """
+ raise exception.NotImplemented()
+
+ def delete_role(self, role_id):
+ """Deletes an existing role.
+
+ :raises: keystone.exception.RoleNotFound
+
+ """
+ raise exception.NotImplemented()
+
+#TODO(ayoung): determine what else these two functions raise
+ def delete_user(self, user_id):
+ """Deletes all assignments for a user.
+
+ :raises: keystone.exception.RoleNotFound
+
+ """
+ raise exception.NotImplemented()
+
+ def delete_group(self, group_id):
+ """Deletes all assignments for a group.
+
+ :raises: keystone.exception.RoleNotFound
+
+ """
+ raise exception.NotImplemented()
+
+ #domain management functions for backends that only allow a single domain.
+ #currently, this is only LDAP, but might be used by PAM or other backends
+ #as well. This is used by both identity and assignment drivers.
+ def _set_default_domain(self, ref):
+ """If the domain ID has not been set, set it to the default."""
+ if isinstance(ref, dict):
+ if 'domain_id' not in ref:
+ ref = ref.copy()
+ ref['domain_id'] = CONF.identity.default_domain_id
+ return ref
+ elif isinstance(ref, list):
+ return [self._set_default_domain(x) for x in ref]
+ else:
+ raise ValueError(_('Expected dict or list: %s') % type(ref))
+
+ def _validate_default_domain(self, ref):
+ """Validate that either the default domain or nothing is specified.
+
+ Also removes the domain from the ref so that LDAP doesn't have to
+ persist the attribute.
+
+ """
+ ref = ref.copy()
+ domain_id = ref.pop('domain_id', CONF.identity.default_domain_id)
+ self._validate_default_domain_id(domain_id)
+ return ref
+
+ def _validate_default_domain_id(self, domain_id):
+ """Validate that the domain ID specified belongs to the default domain.
+
+ """
+ if domain_id != CONF.identity.default_domain_id:
+ raise exception.DomainNotFound(domain_id=domain_id)
diff --git a/keystone/auth/controllers.py b/keystone/auth/controllers.py
index bef4128d..d1bd764f 100644
--- a/keystone/auth/controllers.py
+++ b/keystone/auth/controllers.py
@@ -14,12 +14,11 @@
# License for the specific language governing permissions and limitations
# under the License.
-import json
-from keystone.auth import token_factory
-from keystone.common import cms
from keystone.common import controller
+from keystone.common import dependency
from keystone.common import logging
+from keystone.common import wsgi
from keystone import config
from keystone import exception
from keystone import identity
@@ -190,6 +189,10 @@ class AuthInfo(object):
self._scope_data = (None, None, trust_ref)
def _validate_auth_methods(self):
+ if 'identity' not in self.auth:
+ raise exception.ValidationError(attribute='identity',
+ target='auth')
+
# make sure auth methods are provided
if 'methods' not in self.auth['identity']:
raise exception.ValidationError(attribute='methods',
@@ -222,7 +225,7 @@ class AuthInfo(object):
:returns: list of auth method names
"""
- return self.auth['identity']['methods']
+ return self.auth['identity']['methods'] or []
def get_method_data(self, method):
"""Get the auth method payload.
@@ -267,6 +270,7 @@ class AuthInfo(object):
self._scope_data = (domain_id, project_id, trust)
+@dependency.requires('token_provider_api')
class Auth(controller.V3Controller):
def __init__(self, *args, **kw):
super(Auth, self).__init__(*args, **kw)
@@ -275,19 +279,31 @@ class Auth(controller.V3Controller):
def authenticate_for_token(self, context, auth=None):
"""Authenticate user and issue a token."""
+ include_catalog = 'nocatalog' not in context['query_string']
+
try:
auth_info = AuthInfo(context, auth=auth)
- auth_context = {'extras': {}, 'method_names': []}
+ auth_context = {'extras': {}, 'method_names': [], 'bind': {}}
self.authenticate(context, auth_info, auth_context)
self._check_and_set_default_scoping(auth_info, auth_context)
- (token_id, token_data) = token_factory.create_token(
- auth_context, auth_info)
- return token_factory.render_token_data_response(
- token_id, token_data, created=True)
- except exception.SecurityError:
- raise
- except Exception as e:
- LOG.exception(e)
+ (domain_id, project_id, trust) = auth_info.get_scope()
+ method_names = auth_info.get_method_names()
+ method_names += auth_context.get('method_names', [])
+ # make sure the list is unique
+ method_names = list(set(method_names))
+
+ (token_id, token_data) = self.token_provider_api.issue_token(
+ user_id=auth_context['user_id'],
+ method_names=method_names,
+ expires_at=auth_context.get('expires_at'),
+ project_id=project_id,
+ domain_id=domain_id,
+ auth_context=auth_context,
+ trust=trust,
+ include_catalog=include_catalog)
+ return render_token_data_response(token_id, token_data,
+ created=True)
+ except exception.TrustNotFound as e:
raise exception.Unauthorized(e)
def _check_and_set_default_scoping(self, auth_info, auth_context):
@@ -309,31 +325,13 @@ class Auth(controller.V3Controller):
LOG.exception(e)
raise exception.Unauthorized(e)
- def _build_remote_user_auth_context(self, context, auth_info,
- auth_context):
- username = context['REMOTE_USER']
- # FIXME(gyee): REMOTE_USER is not good enough since we are
- # requiring domain_id to do user lookup now. Try to get
- # the user_id from auth_info for now, assuming external auth
- # has check to make sure user is the same as the one specify
- # in "identity".
- if 'password' in auth_info.get_method_names():
- user_info = auth_info.get_method_data('password')
- user_ref = auth_info.lookup_user(user_info['user'])
- auth_context['user_id'] = user_ref['id']
- else:
- msg = _('Unable to lookup user %s') % (username)
- raise exception.Unauthorized(msg)
-
def authenticate(self, context, auth_info, auth_context):
"""Authenticate user."""
# user have been authenticated externally
if 'REMOTE_USER' in context:
- self._build_remote_user_auth_context(context,
- auth_info,
- auth_context)
- return
+ external = get_auth_method('external')
+ external.authenticate(context, auth_info, auth_context)
# need to aggregate the results in case two or more methods
# are specified
@@ -355,44 +353,41 @@ class Auth(controller.V3Controller):
msg = _('User not found')
raise exception.Unauthorized(msg)
- def _get_token_ref(self, context, token_id, belongs_to=None):
- token_ref = self.token_api.get_token(token_id)
- if cms.is_ans1_token(token_id):
- verified_token = cms.cms_verify(cms.token_to_cms(token_id),
- CONF.signing.certfile,
- CONF.signing.ca_certs)
- token_ref = json.loads(verified_token)
- if belongs_to:
- assert token_ref['project']['id'] == belongs_to
- return token_ref
-
@controller.protected
def check_token(self, context):
- try:
- token_id = context.get('subject_token_id')
- belongs_to = context['query_string'].get('belongsTo')
- assert self._get_token_ref(context, token_id, belongs_to)
- except Exception as e:
- LOG.error(e)
- raise exception.Unauthorized(e)
+ token_id = context.get('subject_token_id')
+ self.token_provider_api.check_token(token_id)
@controller.protected
def revoke_token(self, context):
token_id = context.get('subject_token_id')
- return self.token_controllers_ref.delete_token(context, token_id)
+ return self.token_provider_api.revoke_token(token_id)
@controller.protected
def validate_token(self, context):
token_id = context.get('subject_token_id')
- self.check_token(context)
- token_ref = self.token_api.get_token(token_id)
- token_data = token_factory.recreate_token_data(
- token_ref.get('token_data'),
- token_ref['expires'],
- token_ref.get('user'),
- token_ref.get('tenant'))
- return token_factory.render_token_data_response(token_id, token_data)
+ token_data = self.token_provider_api.validate_token(token_id)
+ return render_token_data_response(token_id, token_data)
@controller.protected
def revocation_list(self, context, auth=None):
return self.token_controllers_ref.revocation_list(context, auth)
+
+
+#FIXME(gyee): not sure if it belongs here or keystone.common. Park it here
+# for now.
+def render_token_data_response(token_id, token_data, created=False):
+ """Render token data HTTP response.
+
+ Stash token ID into the X-Subject-Token header.
+
+ """
+ headers = [('X-Subject-Token', token_id)]
+
+ if created:
+ status = (201, 'Created')
+ else:
+ status = (200, 'OK')
+
+ return wsgi.render_response(body=token_data,
+ status=status, headers=headers)
diff --git a/keystone/auth/plugins/external.py b/keystone/auth/plugins/external.py
new file mode 100644
index 00000000..67b11001
--- /dev/null
+++ b/keystone/auth/plugins/external.py
@@ -0,0 +1,87 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 OpenStack LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+"""Keystone External Authentication Plugin"""
+
+from keystone.common import config
+from keystone import exception
+
+
+CONF = config.CONF
+
+
+class ExternalDefault(object):
+ def authenticate(self, context, auth_info, auth_context):
+ """Use REMOTE_USER to look up the user in the identity backend
+
+ auth_context is an in-out variable that will be updated with the
+ username from the REMOTE_USER environment variable.
+ """
+ try:
+ REMOTE_USER = context['REMOTE_USER']
+ except KeyError:
+ msg = _('No authenticated user')
+ raise exception.Unauthorized(msg)
+ try:
+ names = REMOTE_USER.split('@')
+ username = names.pop(0)
+ domain_id = CONF.identity.default_domain_id
+ user_ref = auth_info.identity_api.get_user_by_name(username,
+ domain_id)
+ auth_context['user_id'] = user_ref['id']
+ if ('kerberos' in CONF.token.bind and
+ context.get('AUTH_TYPE', '').lower() == 'negotiate'):
+ auth_context['bind']['kerberos'] = username
+ except Exception:
+ msg = _('Unable to lookup user %s') % (REMOTE_USER)
+ raise exception.Unauthorized(msg)
+
+
+class ExternalDomain(object):
+ def authenticate(self, context, auth_info, auth_context):
+ """Use REMOTE_USER to look up the user in the identity backend
+
+ auth_context is an in-out variable that will be updated with the
+ username from the REMOTE_USER environment variable.
+
+ If REMOTE_USER contains an `@` assume that the substring before the @
+ is the username, and the substring after the @ is the domain name.
+ """
+ try:
+ REMOTE_USER = context['REMOTE_USER']
+ except KeyError:
+ msg = _('No authenticated user')
+ raise exception.Unauthorized(msg)
+ try:
+ names = REMOTE_USER.split('@')
+ username = names.pop(0)
+ if names:
+ domain_name = names[0]
+ domain_ref = (auth_info.identity_api.
+ get_domain_by_name(domain_name))
+ domain_id = domain_ref['id']
+ else:
+ domain_id = CONF.identity.default_domain_id
+ user_ref = auth_info.identity_api.get_user_by_name(username,
+ domain_id)
+ auth_context['user_id'] = user_ref['id']
+ if ('kerberos' in CONF.token.bind and
+ context.get('AUTH_TYPE', '').lower() == 'negotiate'):
+ auth_context['bind']['kerberos'] = username
+
+ except Exception:
+ msg = _('Unable to lookup user %s') % (REMOTE_USER)
+ raise exception.Unauthorized(msg)
diff --git a/keystone/auth/plugins/password.py b/keystone/auth/plugins/password.py
index 631ce08d..f3cfeba8 100644
--- a/keystone/auth/plugins/password.py
+++ b/keystone/auth/plugins/password.py
@@ -103,8 +103,14 @@ class Password(auth.AuthMethodHandler):
# FIXME(gyee): identity.authenticate() can use some refactoring since
# all we care is password matches
- self.identity_api.authenticate(
- user_id=user_info.user_id,
- password=user_info.password)
+ try:
+ self.identity_api.authenticate(
+ user_id=user_info.user_id,
+ password=user_info.password)
+ except AssertionError:
+ # authentication failed because of invalid username or password
+ msg = _('Invalid username or password')
+ raise exception.Unauthorized(msg)
+
if 'user_id' not in user_context:
user_context['user_id'] = user_info.user_id
diff --git a/keystone/auth/plugins/token.py b/keystone/auth/plugins/token.py
index d9b3d2f8..720eccac 100644
--- a/keystone/auth/plugins/token.py
+++ b/keystone/auth/plugins/token.py
@@ -16,6 +16,7 @@
from keystone import auth
from keystone.common import logging
+from keystone.common import wsgi
from keystone import exception
from keystone import token
@@ -36,6 +37,7 @@ class Token(auth.AuthMethodHandler):
target=METHOD_NAME)
token_id = auth_payload['id']
token_ref = self.token_api.get_token(token_id)
+ wsgi.validate_token_bind(context, token_ref)
user_context.setdefault(
'user_id', token_ref['token_data']['token']['user']['id'])
# to support Grizzly-3 to Grizzly-RC1 transition
@@ -46,7 +48,8 @@ class Token(auth.AuthMethodHandler):
token_ref['token_data']['token']['extras'])
user_context['method_names'].extend(
token_ref['token_data']['token']['methods'])
- if 'trust' in token_ref['token_data']:
+ if ('OS-TRUST:trust' in token_ref['token_data']['token'] or
+ 'trust' in token_ref['token_data']['token']):
raise exception.Forbidden()
except AssertionError as e:
LOG.error(e)
diff --git a/keystone/auth/token_factory.py b/keystone/auth/token_factory.py
deleted file mode 100644
index 22bc8363..00000000
--- a/keystone/auth/token_factory.py
+++ /dev/null
@@ -1,368 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2013 OpenStack LLC
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-"""Token Factory"""
-
-import json
-import sys
-import uuid
-import webob
-
-from keystone import catalog
-from keystone.common import cms
-from keystone.common import environment
-from keystone.common import logging
-from keystone.common import utils
-from keystone import config
-from keystone import exception
-from keystone import identity
-from keystone.openstack.common import jsonutils
-from keystone.openstack.common import timeutils
-from keystone import token as token_module
-from keystone import trust
-
-
-CONF = config.CONF
-
-LOG = logging.getLogger(__name__)
-
-
-class TokenDataHelper(object):
- """Token data helper."""
- def __init__(self):
- self.identity_api = identity.Manager()
- self.catalog_api = catalog.Manager()
- self.trust_api = trust.Manager()
-
- def _get_filtered_domain(self, domain_id):
- domain_ref = self.identity_api.get_domain(domain_id)
- return {'id': domain_ref['id'], 'name': domain_ref['name']}
-
- def _populate_scope(self, token_data, domain_id, project_id):
- if 'domain' in token_data or 'project' in token_data:
- return
-
- if domain_id:
- token_data['domain'] = self._get_filtered_domain(domain_id)
- if project_id:
- project_ref = self.identity_api.get_project(project_id)
- filtered_project = {
- 'id': project_ref['id'],
- 'name': project_ref['name']}
- filtered_project['domain'] = self._get_filtered_domain(
- project_ref['domain_id'])
- token_data['project'] = filtered_project
-
- def _get_project_roles_for_user(self, user_id, project_id):
- roles = self.identity_api.get_roles_for_user_and_project(
- user_id, project_id)
- roles_ref = []
- for role_id in roles:
- role_ref = self.identity_api.get_role(role_id)
- role_ref.setdefault('project_id', project_id)
- roles_ref.append(role_ref)
- # user have no project roles, therefore access denied
- if len(roles_ref) == 0:
- msg = _('User have no access to project')
- LOG.debug(msg)
- raise exception.Unauthorized(msg)
- return roles_ref
-
- def _get_domain_roles_for_user(self, user_id, domain_id):
- roles = self.identity_api.get_roles_for_user_and_domain(
- user_id, domain_id)
- roles_ref = []
- for role_id in roles:
- role_ref = self.identity_api.get_role(role_id)
- role_ref.setdefault('domain_id', domain_id)
- roles_ref.append(role_ref)
- # user have no domain roles, therefore access denied
- if len(roles_ref) == 0:
- msg = _('User have no access to domain')
- LOG.debug(msg)
- raise exception.Unauthorized(msg)
- return roles_ref
-
- def _get_roles_for_user(self, user_id, domain_id, project_id):
- roles = []
- if domain_id:
- roles = self._get_domain_roles_for_user(user_id, domain_id)
- if project_id:
- roles = self._get_project_roles_for_user(user_id, project_id)
- return roles
-
- def _populate_user(self, token_data, user_id, domain_id, project_id,
- trust):
- if 'user' in token_data:
- return
-
- user_ref = self.identity_api.get_user(user_id)
- if CONF.trust.enabled and trust:
- trustor_user_ref = self.identity_api.get_user(
- trust['trustor_user_id'])
- if not trustor_user_ref['enabled']:
- raise exception.Forbidden()
- if trust['impersonation']:
- user_ref = trustor_user_ref
- token_data['OS-TRUST:trust'] = (
- {
- 'id': trust['id'],
- 'trustor_user': {'id': trust['trustor_user_id']},
- 'trustee_user': {'id': trust['trustee_user_id']},
- 'impersonation': trust['impersonation']
- })
- filtered_user = {
- 'id': user_ref['id'],
- 'name': user_ref['name'],
- 'domain': self._get_filtered_domain(user_ref['domain_id'])}
- token_data['user'] = filtered_user
-
- def _populate_roles(self, token_data, user_id, domain_id, project_id,
- trust):
- if 'roles' in token_data:
- return
-
- if CONF.trust.enabled and trust:
- token_user_id = trust['trustor_user_id']
- token_project_id = trust['project_id']
- #trusts do not support domains yet
- token_domain_id = None
- else:
- token_user_id = user_id
- token_project_id = project_id
- token_domain_id = domain_id
-
- if token_domain_id or token_project_id:
- roles = self._get_roles_for_user(token_user_id,
- token_domain_id,
- token_project_id)
- filtered_roles = []
- if CONF.trust.enabled and trust:
- for trust_role in trust['roles']:
- match_roles = [x for x in roles
- if x['id'] == trust_role['id']]
- if match_roles:
- filtered_roles.append(match_roles[0])
- else:
- raise exception.Forbidden()
- else:
- for role in roles:
- filtered_roles.append({'id': role['id'],
- 'name': role['name']})
- token_data['roles'] = filtered_roles
-
- def _populate_service_catalog(self, token_data, user_id,
- domain_id, project_id, trust):
- if 'catalog' in token_data:
- return
-
- if CONF.trust.enabled and trust:
- user_id = trust['trustor_user_id']
- if project_id or domain_id:
- try:
- service_catalog = self.catalog_api.get_v3_catalog(
- user_id, project_id)
- # TODO(ayoung): KVS backend needs a sample implementation
- except exception.NotImplemented:
- service_catalog = {}
- # TODO(gyee): v3 service catalog is not quite completed yet
- # TODO(ayoung): Enforce Endpoints for trust
- token_data['catalog'] = service_catalog
-
- def _populate_token(self, token_data, expires=None, trust=None):
- if not expires:
- expires = token_module.default_expire_time()
- if not isinstance(expires, basestring):
- expires = timeutils.isotime(expires, subsecond=True)
- token_data['expires_at'] = expires
- token_data['issued_at'] = timeutils.isotime(subsecond=True)
-
- def get_token_data(self, user_id, method_names, extras,
- domain_id=None, project_id=None, expires=None,
- trust=None, token=None):
- token_data = {'methods': method_names,
- 'extras': extras}
-
- # We've probably already written these to the token
- for x in ('roles', 'user', 'catalog', 'project', 'domain'):
- if token and x in token:
- token_data[x] = token[x]
-
- if CONF.trust.enabled and trust:
- if user_id != trust['trustee_user_id']:
- raise exception.Forbidden()
-
- self._populate_scope(token_data, domain_id, project_id)
- self._populate_user(token_data, user_id, domain_id, project_id, trust)
- self._populate_roles(token_data, user_id, domain_id, project_id, trust)
- self._populate_service_catalog(token_data, user_id, domain_id,
- project_id, trust)
- self._populate_token(token_data, expires, trust)
- return {'token': token_data}
-
-
-def recreate_token_data(token_data=None, expires=None,
- user_ref=None, project_ref=None):
- """Recreate token from an existing token.
-
- Repopulate the ephemeral data and return the new token data.
-
- """
- new_expires = expires
- project_id = None
- user_id = None
- domain_id = None
- methods = ['password', 'token']
- extras = {}
-
- # NOTE(termie): Let's get some things straight here, because this code
- # is wrong but tested as such:
- # token_data, if it exists, is going to look like:
- # {'token': ... the actual token data + a superfluous extras field ...}
- # this data is actually stored in the database in the 'extras' column and
- # then deserialized and added to the token_ref, that already has the
- # the 'expires', 'user_id', and 'id' columns from the db.
- # the 'user' and 'tenant' fields are being added to the
- # token_ref due to being deserialized from the 'extras' column
- #
- # So, how this all looks in the db:
- # id = some_id
- # user_id = some_user_id
- # expires = some_expiration
- # extras = {'user': {'id': some_used_id},
- # 'tenant': {'id': some_tenant_id},
- # 'token_data': 'token': {'domain': {'id': some_domain_id},
- # 'project': {'id': some_project_id},
- # 'domain': {'id': some_domain_id},
- # 'user': {'id': some_user_id},
- # 'roles': [{'id': some_role_id}, ...],
- # 'catalog': ...,
- # 'expires_at': some_expiry_time,
- # 'issued_at': now(),
- # 'methods': ['password', 'token'],
- # 'extras': { ... empty? ...}
- #
- # TODO(termie): reduce stored token complexity, bug filed at:
- # https://bugs.launchpad.net/keystone/+bug/1159990
- if token_data:
- # peel the outer layer so its easier to operate
- token = token_data['token']
- domain_id = (token['domain']['id'] if 'domain' in token
- else None)
- project_id = (token['project']['id'] if 'project' in token
- else None)
- if not new_expires:
- # support Grizzly-3 to Grizzly-RC1 transition
- # tokens issued in G3 has 'expires' instead of 'expires_at'
- new_expires = token.get('expires_at',
- token.get('expires'))
- user_id = token['user']['id']
- methods = token['methods']
- extras = token['extras']
- else:
- token = None
- project_id = project_ref['id'] if project_ref else None
- user_id = user_ref['id']
- token_data_helper = TokenDataHelper()
- return token_data_helper.get_token_data(user_id,
- methods,
- extras,
- domain_id,
- project_id,
- new_expires,
- token=token)
-
-
-def create_token(auth_context, auth_info):
- token_data_helper = TokenDataHelper()
- (domain_id, project_id, trust) = auth_info.get_scope()
- method_names = list(set(auth_info.get_method_names() +
- auth_context.get('method_names', [])))
- token_data = token_data_helper.get_token_data(
- auth_context['user_id'],
- method_names,
- auth_context['extras'],
- domain_id,
- project_id,
- auth_context.get('expires_at', None),
- trust)
-
- if CONF.signing.token_format == 'UUID':
- token_id = uuid.uuid4().hex
- elif CONF.signing.token_format == 'PKI':
- try:
- token_id = cms.cms_sign_token(json.dumps(token_data),
- CONF.signing.certfile,
- CONF.signing.keyfile)
- except environment.subprocess.CalledProcessError:
- raise exception.UnexpectedError(_(
- 'Unable to sign token.'))
- else:
- raise exception.UnexpectedError(_(
- 'Invalid value for token_format: %s.'
- ' Allowed values are PKI or UUID.') %
- CONF.signing.token_format)
- token_api = token_module.Manager()
- try:
- expiry = token_data['token']['expires_at']
- if isinstance(expiry, basestring):
- expiry = timeutils.normalize_time(timeutils.parse_isotime(expiry))
- role_ids = []
- if 'project' in token_data['token']:
- # project-scoped token, fill in the v2 token data
- # all we care are the role IDs
- role_ids = [role['id'] for role in token_data['token']['roles']]
- metadata_ref = {'roles': role_ids}
- data = dict(key=token_id,
- id=token_id,
- expires=expiry,
- user=token_data['token']['user'],
- tenant=token_data['token'].get('project'),
- metadata=metadata_ref,
- token_data=token_data,
- trust_id=trust['id'] if trust else None)
- token_api.create_token(token_id, data)
- except Exception:
- exc_info = sys.exc_info()
- # an identical token may have been created already.
- # if so, return the token_data as it is also identical
- try:
- token_api.get_token(token_id)
- except exception.TokenNotFound:
- raise exc_info[0], exc_info[1], exc_info[2]
-
- return (token_id, token_data)
-
-
-def render_token_data_response(token_id, token_data, created=False):
- """Render token data HTTP response.
-
- Stash token ID into the X-Auth-Token header.
-
- """
- headers = [('X-Subject-Token', token_id)]
- headers.append(('Vary', 'X-Auth-Token'))
- headers.append(('Content-Type', 'application/json'))
-
- if created:
- status = (201, 'Created')
- else:
- status = (200, 'OK')
-
- body = jsonutils.dumps(token_data, cls=utils.SmarterEncoder)
- return webob.Response(body=body,
- status='%s %s' % status,
- headerlist=headers)
diff --git a/keystone/cli.py b/keystone/cli.py
index 598bd409..21d2ad40 100644
--- a/keystone/cli.py
+++ b/keystone/cli.py
@@ -74,7 +74,7 @@ class DbVersion(BaseApp):
@staticmethod
def main():
- print migration.db_version()
+ print(migration.db_version())
class BaseCertificateSetup(BaseApp):
@@ -180,7 +180,7 @@ class ExportLegacyCatalog(BaseApp):
def main():
from keystone.common.sql import legacy
migration = legacy.LegacyMigration(CONF.command.old_db)
- print '\n'.join(migration.dump_catalog())
+ print('\n'.join(migration.dump_catalog()))
class ImportNovaAuth(BaseApp):
diff --git a/keystone/common/config.py b/keystone/common/config.py
index c0bd34e6..10c47a35 100644
--- a/keystone/common/config.py
+++ b/keystone/common/config.py
@@ -24,7 +24,7 @@ from keystone.common import logging
_DEFAULT_LOG_FORMAT = "%(asctime)s %(levelname)8s [%(name)s] %(message)s"
_DEFAULT_LOG_DATE_FORMAT = "%Y-%m-%d %H:%M:%S"
-_DEFAULT_AUTH_METHODS = ['password', 'token']
+_DEFAULT_AUTH_METHODS = ['external', 'password', 'token']
COMMON_CLI_OPTS = [
cfg.BoolOpt('debug',
@@ -214,6 +214,13 @@ def configure():
# trust
register_bool('enabled', group='trust', default=True)
+ # os_inherit
+ register_bool('enabled', group='os_inherit', default=False)
+
+ # binding
+ register_list('bind', group='token', default=[])
+ register_str('enforce_token_bind', group='token', default='permissive')
+
# ssl
register_bool('enable', group='ssl', default=False)
register_str('certfile', group='ssl',
@@ -233,7 +240,7 @@ def configure():
# signing
register_str(
- 'token_format', group='signing', default="PKI")
+ 'token_format', group='signing', default=None)
register_str(
'certfile',
group='signing',
@@ -259,6 +266,12 @@ def configure():
default='sqlite:///keystone.db')
register_int('idle_timeout', group='sql', default=200)
+ #assignment has no default for backward compatibility reasons.
+ #If assignment is not specified, the identity driver chooses the backend
+ register_str(
+ 'driver',
+ group='assignment',
+ default=None)
register_str(
'driver',
group='catalog',
@@ -369,23 +382,6 @@ def configure():
register_list(
'group_additional_attribute_mapping', group='ldap', default=None)
- register_str('domain_tree_dn', group='ldap', default=None)
- register_str('domain_filter', group='ldap', default=None)
- register_str('domain_objectclass', group='ldap', default='groupOfNames')
- register_str('domain_id_attribute', group='ldap', default='cn')
- register_str('domain_name_attribute', group='ldap', default='ou')
- register_str('domain_member_attribute', group='ldap', default='member')
- register_str('domain_desc_attribute', group='ldap', default='description')
- register_str('domain_enabled_attribute', group='ldap', default='enabled')
- register_list('domain_attribute_ignore', group='ldap', default='')
- register_bool('domain_allow_create', group='ldap', default=True)
- register_bool('domain_allow_update', group='ldap', default=True)
- register_bool('domain_allow_delete', group='ldap', default=True)
- register_bool('domain_enabled_emulation', group='ldap', default=False)
- register_str('domain_enabled_emulation_dn', group='ldap', default=None)
- register_list(
- 'domain_additional_attribute_mapping', group='ldap', default=None)
-
register_str('tls_cacertfile', group='ldap', default=None)
register_str('tls_cacertdir', group='ldap', default=None)
register_bool('use_tls', group='ldap', default=False)
@@ -402,7 +398,11 @@ def configure():
register_str(
'token', group='auth',
default='keystone.auth.plugins.password.Password')
-
+ #deals with REMOTE_USER authentication
+ register_str(
+ 'external',
+ group='auth',
+ default='keystone.auth.plugins.external.ExternalDefault')
# register any non-default auth methods here (used by extensions, etc)
for method_name in CONF.auth.methods:
if method_name not in _DEFAULT_AUTH_METHODS:
@@ -410,3 +410,9 @@ def configure():
# PasteDeploy config file
register_str('config_file', group='paste_deploy', default=None)
+
+ # token provider
+ register_str(
+ 'provider',
+ group='token',
+ default=None)
diff --git a/keystone/common/controller.py b/keystone/common/controller.py
index 13aeee57..affc34de 100644
--- a/keystone/common/controller.py
+++ b/keystone/common/controller.py
@@ -25,8 +25,12 @@ def _build_policy_check_credentials(self, action, context, kwargs):
LOG.warning(_('RBAC: Invalid token'))
raise exception.Unauthorized()
+ # NOTE(jamielennox): whilst this maybe shouldn't be within this function
+ # it would otherwise need to reload the token_ref from backing store.
+ wsgi.validate_token_bind(context, token_ref)
+
creds = {}
- if 'token_data' in token_ref:
+ if 'token_data' in token_ref and 'token' in token_ref['token_data']:
#V3 Tokens
token_data = token_ref['token_data']['token']
try:
@@ -146,7 +150,8 @@ def filterprotected(*filters):
@dependency.requires('identity_api', 'policy_api', 'token_api',
- 'trust_api', 'catalog_api', 'credential_api')
+ 'trust_api', 'catalog_api', 'credential_api',
+ 'assignment_api')
class V2Controller(wsgi.Application):
"""Base controller class for Identity API v2."""
@@ -280,7 +285,8 @@ class V3Controller(V2Controller):
if attr in context['query_string']:
value = context['query_string'][attr]
- return [r for r in refs if _attr_match(r[attr], value)]
+ return [r for r in refs if _attr_match(
+ flatten(r).get(attr), value)]
return refs
def _require_matching_id(self, value, ref):
@@ -311,7 +317,7 @@ class V3Controller(V2Controller):
# worth the duplication of state
try:
token_ref = self.token_api.get_token(
- context=context, token_id=context['token_id'])
+ token_id=context['token_id'])
except exception.TokenNotFound:
LOG.warning(_('Invalid token in normalize_domain_id'))
raise exception.Unauthorized()
diff --git a/keystone/common/dependency.py b/keystone/common/dependency.py
index dc3e4ac4..a640031d 100644
--- a/keystone/common/dependency.py
+++ b/keystone/common/dependency.py
@@ -16,6 +16,8 @@
REGISTRY = {}
+_future_dependencies = {}
+
class UnresolvableDependencyException(Exception):
def __init__(self, name):
@@ -32,6 +34,8 @@ def provider(name):
init(self, *args, **kwargs)
REGISTRY[name] = self
+ resolve_future_dependencies(name)
+
return __wrapped_init__
cls.__init__ = wrapped(cls.__init__)
@@ -48,7 +52,13 @@ def requires(*dependencies):
for dependency in self._dependencies:
if dependency not in REGISTRY:
- raise UnresolvableDependencyException(dependency)
+ if dependency in _future_dependencies:
+ _future_dependencies[dependency] += [self]
+ else:
+ _future_dependencies[dependency] = [self]
+
+ continue
+
setattr(self, dependency, REGISTRY[dependency])
def wrapped(cls):
@@ -65,3 +75,34 @@ def requires(*dependencies):
return cls
return wrapped
+
+
+def resolve_future_dependencies(provider_name=None):
+ if provider_name:
+ targets = _future_dependencies.pop(provider_name, [])
+
+ for target in targets:
+ setattr(target, provider_name, REGISTRY[provider_name])
+
+ return
+
+ try:
+ for dependency, targets in _future_dependencies.iteritems():
+ if dependency not in REGISTRY:
+ raise UnresolvableDependencyException(dependency)
+
+ for target in targets:
+ setattr(target, dependency, REGISTRY[dependency])
+ finally:
+ _future_dependencies.clear()
+
+
+def reset():
+ """Reset the registry of providers.
+
+ This is useful for unit testing to ensure that tests don't use providers
+ from previous tests.
+ """
+
+ REGISTRY.clear()
+ _future_dependencies.clear()
diff --git a/keystone/common/extension.py b/keystone/common/extension.py
new file mode 100644
index 00000000..f176a197
--- /dev/null
+++ b/keystone/common/extension.py
@@ -0,0 +1,47 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 OpenStack LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+
+ADMIN_EXTENSIONS = {}
+PUBLIC_EXTENSIONS = {}
+
+
+def register_admin_extension(url_prefix, extension_data):
+ """Register extension with collection of admin extensions.
+
+ Extensions register the information here that will show
+ up in the /extensions page as a way to indicate that the extension is
+ active.
+
+ url_prefix: unique key for the extension that will appear in the
+ urls generated by the extension.
+
+ extension_data is a dictionary. The expected fields are:
+ 'name': short, human readable name of the extnsion
+ 'namespace': xml namespace
+ 'alias': identifier for the extension
+ 'updated': date the extension was last updated
+ 'description': text description of the extension
+ 'links': hyperlinks to documents describing the extension
+
+ """
+ ADMIN_EXTENSIONS[url_prefix] = extension_data
+
+
+def register_public_extension(url_prefix, extension_data):
+ """Same as register_admin_extension but for public extensions."""
+
+ PUBLIC_EXTENSIONS[url_prefix] = extension_data
diff --git a/keystone/common/kvs.py b/keystone/common/kvs.py
index b517bc5d..09693999 100644
--- a/keystone/common/kvs.py
+++ b/keystone/common/kvs.py
@@ -50,6 +50,8 @@ class Base(object):
def __init__(self, db=None):
if db is None:
db = INMEMDB
+ elif isinstance(db, DictKvs):
+ db = db
elif isinstance(db, dict):
db = DictKvs(db)
self.db = db
diff --git a/keystone/common/logging.py b/keystone/common/logging.py
index 8c036f02..d221edb7 100644
--- a/keystone/common/logging.py
+++ b/keystone/common/logging.py
@@ -23,7 +23,6 @@ import logging
import logging.config
import logging.handlers
import pprint
-import traceback
# A list of things we want to replicate from logging.
@@ -78,8 +77,7 @@ def fail_gracefully(f):
try:
return f(*args, **kw)
except Exception as e:
- # tracebacks are kept in the debug log
- logging.debug(traceback.format_exc(e))
+ logging.debug(e, exc_info=True)
# exception message is printed to all logs
logging.critical(e)
diff --git a/keystone/common/openssl.py b/keystone/common/openssl.py
index 427202ae..fa09e37c 100644
--- a/keystone/common/openssl.py
+++ b/keystone/common/openssl.py
@@ -12,6 +12,7 @@
# 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
diff --git a/keystone/common/serializer.py b/keystone/common/serializer.py
index 597fbfd8..4355a059 100644
--- a/keystone/common/serializer.py
+++ b/keystone/common/serializer.py
@@ -125,7 +125,8 @@ class XmlDeserializer(object):
values = values or text or {}
decoded_tag = XmlDeserializer._tag_name(element.tag, namespace)
list_item_tag = None
- if decoded_tag[-1] == 's' and len(values) == 0:
+ if (decoded_tag[-1] == 's' and len(values) == 0 and
+ decoded_tag != 'access'):
# FIXME(gyee): special-case lists for now unti we
# figure out how to properly handle them.
# If any key ends with an 's', we are assuming it is a list.
diff --git a/keystone/common/sql/core.py b/keystone/common/sql/core.py
index d75c73a8..2d3114f2 100644
--- a/keystone/common/sql/core.py
+++ b/keystone/common/sql/core.py
@@ -32,10 +32,12 @@ from keystone import exception
from keystone.openstack.common import jsonutils
+LOG = logging.getLogger(__name__)
CONF = config.CONF
-# maintain a single engine reference for sqlite in-memory
+# maintain a single engine reference for sqlalchemy engine
GLOBAL_ENGINE = None
+GLOBAL_ENGINE_CALLBACKS = set()
ModelBase = declarative.declarative_base()
@@ -78,13 +80,6 @@ def initialize_decorator(init):
v = str(v)
if column.type.length and \
column.type.length < len(v):
- #if signing.token_format == 'PKI', the id will
- #store it's public key which is very long.
- if config.CONF.signing.token_format == 'PKI' and \
- self.__tablename__ == 'token' and \
- k == 'id':
- continue
-
raise exception.StringLengthExceeded(
string=v, type=k, length=column.type.length)
@@ -95,9 +90,49 @@ ModelBase.__init__ = initialize_decorator(ModelBase.__init__)
def set_global_engine(engine):
+ """Set the global engine.
+
+ This sets the current global engine, which is returned by
+ Base.get_engine(allow_global_engine=True).
+
+ When the global engine is changed, all of the callbacks registered via
+ register_global_engine_callback since the last time set_global_engine was
+ changed are called. The callback functions are invoked with no arguments.
+
+ """
+
global GLOBAL_ENGINE
+ global GLOBAL_ENGINE_CALLBACKS
+
+ if engine is GLOBAL_ENGINE:
+ # It's the same engine so nothing to do.
+ return
+
GLOBAL_ENGINE = engine
+ cbs = GLOBAL_ENGINE_CALLBACKS
+ GLOBAL_ENGINE_CALLBACKS = set()
+ for cb in cbs:
+ try:
+ cb()
+ except Exception:
+ LOG.exception(_("Global engine callback raised."))
+ # Just logging the exception so can process other callbacks.
+
+
+def register_global_engine_callback(cb_fn):
+ """Register a function to be called when the global engine is set.
+
+ Note that the callback will be called only once or not at all, so to get
+ called each time the global engine is changed the function must be
+ re-registered.
+
+ """
+
+ global GLOBAL_ENGINE_CALLBACKS
+
+ GLOBAL_ENGINE_CALLBACKS.add(cb_fn)
+
# Special Fields
class JsonBlob(sql_types.TypeDecorator):
@@ -208,10 +243,12 @@ class Base(object):
def get_session(self, autocommit=True, expire_on_commit=False):
"""Return a SQLAlchemy session."""
- self._engine = self._engine or self.get_engine()
- self._sessionmaker = self._sessionmaker or self.get_sessionmaker(
- self._engine)
- return self._sessionmaker()
+ if not self._engine:
+ self._engine = self.get_engine()
+ self._sessionmaker = self.get_sessionmaker(self._engine)
+ register_global_engine_callback(self.clear_engine)
+ return self._sessionmaker(autocommit=autocommit,
+ expire_on_commit=expire_on_commit)
def get_engine(self, allow_global_engine=True):
"""Return a SQLAlchemy engine.
@@ -264,6 +301,10 @@ class Base(object):
autocommit=autocommit,
expire_on_commit=expire_on_commit)
+ def clear_engine(self):
+ self._engine = None
+ self._sessionmaker = None
+
def handle_conflicts(type='object'):
"""Converts IntegrityError into HTTP 409 Conflict."""
diff --git a/keystone/common/sql/legacy.py b/keystone/common/sql/legacy.py
index f2e0b994..c8adc900 100644
--- a/keystone/common/sql/legacy.py
+++ b/keystone/common/sql/legacy.py
@@ -19,6 +19,8 @@ import re
import sqlalchemy
from sqlalchemy import exc
+
+from keystone.assignment.backends import sql as assignment_sql
from keystone.common import logging
from keystone import config
from keystone.contrib.ec2.backends import sql as ec2_sql
@@ -57,8 +59,14 @@ def _translate_replacements(s):
class LegacyMigration(object):
def __init__(self, db_string):
self.db = sqlalchemy.create_engine(db_string)
+ #TODO(ayoung): Replace with call via Manager
self.identity_driver = identity_sql.Identity()
+ self.assignment_driver = assignment_sql.Assignment()
+ self.identity_driver.assignment_api = self.assignment_driver
+ self.assignment_driver.identity_api = self.identity_driver
self.identity_driver.db_sync()
+ self.assignment_driver.db_sync()
+
self.ec2_driver = ec2_sql.Ec2()
self._data = {}
self._user_map = {}
@@ -113,7 +121,7 @@ class LegacyMigration(object):
self._project_map[x.get('id')] = new_dict['id']
# create
#print 'create_project(%s, %s)' % (new_dict['id'], new_dict)
- self.identity_driver.create_project(new_dict['id'], new_dict)
+ self.assignment_driver.create_project(new_dict['id'], new_dict)
def _migrate_users(self):
for x in self._data['users']:
@@ -144,7 +152,7 @@ class LegacyMigration(object):
# track internal ids
self._role_map[x.get('id')] = new_dict['id']
# create
- self.identity_driver.create_role(new_dict['id'], new_dict)
+ self.assignment_driver.create_role(new_dict['id'], new_dict)
def _migrate_user_roles(self):
for x in self._data['user_roles']:
@@ -162,7 +170,7 @@ class LegacyMigration(object):
except Exception:
pass
- self.identity_driver.add_role_to_user_and_project(
+ self.assignment_driver.add_role_to_user_and_project(
user_id, tenant_id, role_id)
def _migrate_tokens(self):
diff --git a/keystone/common/sql/migrate_repo/versions/001_add_initial_tables.py b/keystone/common/sql/migrate_repo/versions/001_add_initial_tables.py
index d29cf167..84243cb9 100644
--- a/keystone/common/sql/migrate_repo/versions/001_add_initial_tables.py
+++ b/keystone/common/sql/migrate_repo/versions/001_add_initial_tables.py
@@ -54,12 +54,28 @@ def upgrade(migrate_engine):
sql.Column('name', sql.String(255), unique=True, nullable=False))
role_table.create(migrate_engine, checkfirst=True)
- tenant_table = sql.Table(
- 'tenant',
- meta,
- sql.Column('id', sql.String(64), primary_key=True),
- sql.Column('name', sql.String(64), unique=True, nullable=False),
- sql.Column('extra', sql.Text()))
+ if migrate_engine.name == 'ibm_db_sa':
+ # NOTE(blk-u): SQLAlchemy for PostgreSQL picks the name tenant_name_key
+ # for the unique constraint, but for DB2 doesn't give the UC a name
+ # unless we tell it to and there is no DDL to alter a column to drop
+ # an unnamed unique constraint, so this code creates a named unique
+ # constraint on the name column rather than an unnamed one.
+ # (This is used in migration 16.)
+ tenant_table = sql.Table(
+ 'tenant',
+ meta,
+ sql.Column('id', sql.String(64), primary_key=True),
+ sql.Column('name', sql.String(64), nullable=False),
+ sql.Column('extra', sql.Text()),
+ sql.UniqueConstraint('name', name='tenant_name_key'))
+ else:
+ tenant_table = sql.Table(
+ 'tenant',
+ meta,
+ sql.Column('id', sql.String(64), primary_key=True),
+ sql.Column('name', sql.String(64), unique=True, nullable=False),
+ sql.Column('extra', sql.Text()))
+
tenant_table.create(migrate_engine, checkfirst=True)
metadata_table = sql.Table(
@@ -79,12 +95,28 @@ def upgrade(migrate_engine):
sql.Column('tenant_id', sql.String(64)))
ec2_credential_table.create(migrate_engine, checkfirst=True)
- user_table = sql.Table(
- 'user',
- meta,
- sql.Column('id', sql.String(64), primary_key=True),
- sql.Column('name', sql.String(64), unique=True, nullable=False),
- sql.Column('extra', sql.Text()))
+ if migrate_engine.name == 'ibm_db_sa':
+ # NOTE(blk-u): SQLAlchemy for PostgreSQL picks the name user_name_key
+ # for the unique constraint, but for DB2 doesn't give the UC a name
+ # unless we tell it to and there is no DDL to alter a column to drop
+ # an unnamed unique constraint, so this code creates a named unique
+ # constraint on the name column rather than an unnamed one.
+ # (This is used in migration 16.)
+ user_table = sql.Table(
+ 'user',
+ meta,
+ sql.Column('id', sql.String(64), primary_key=True),
+ sql.Column('name', sql.String(64), nullable=False),
+ sql.Column('extra', sql.Text()),
+ sql.UniqueConstraint('name', name='user_name_key'))
+ else:
+ user_table = sql.Table(
+ 'user',
+ meta,
+ sql.Column('id', sql.String(64), primary_key=True),
+ sql.Column('name', sql.String(64), unique=True, nullable=False),
+ sql.Column('extra', sql.Text()))
+
user_table.create(migrate_engine, checkfirst=True)
user_tenant_membership_table = sql.Table(
diff --git a/keystone/common/sql/migrate_repo/versions/011_endpoints_v3.py b/keystone/common/sql/migrate_repo/versions/011_endpoints_v3.py
index 31117486..b0f88086 100644
--- a/keystone/common/sql/migrate_repo/versions/011_endpoints_v3.py
+++ b/keystone/common/sql/migrate_repo/versions/011_endpoints_v3.py
@@ -16,6 +16,8 @@
import sqlalchemy as sql
+from keystone.common.sql import migration_helpers
+
def upgrade(migrate_engine):
"""Create API-version specific endpoint tables."""
@@ -23,7 +25,14 @@ def upgrade(migrate_engine):
meta.bind = migrate_engine
legacy_table = sql.Table('endpoint', meta, autoload=True)
- legacy_table.rename('endpoint_v2')
+
+ renames = {'endpoint_v2': legacy_table}
+ service_table = sql.Table('service', meta, autoload=True)
+ constraints = [{'table': legacy_table,
+ 'fk_column': 'service_id',
+ 'ref_column': service_table.c.id}]
+ migration_helpers.rename_tables_with_constraints(renames, constraints,
+ migrate_engine)
sql.Table('service', meta, autoload=True)
new_table = sql.Table(
@@ -51,4 +60,11 @@ def downgrade(migrate_engine):
new_table.drop()
legacy_table = sql.Table('endpoint_v2', meta, autoload=True)
- legacy_table.rename('endpoint')
+
+ renames = {'endpoint': legacy_table}
+ service_table = sql.Table('service', meta, autoload=True)
+ constraints = [{'table': legacy_table,
+ 'fk_column': 'service_id',
+ 'ref_column': service_table.c.id}]
+ migration_helpers.rename_tables_with_constraints(renames, constraints,
+ migrate_engine)
diff --git a/keystone/common/sql/migrate_repo/versions/013_drop_legacy_endpoints.py b/keystone/common/sql/migrate_repo/versions/013_drop_legacy_endpoints.py
index f75ce3c0..deb52947 100644
--- a/keystone/common/sql/migrate_repo/versions/013_drop_legacy_endpoints.py
+++ b/keystone/common/sql/migrate_repo/versions/013_drop_legacy_endpoints.py
@@ -16,6 +16,8 @@
import sqlalchemy as sql
+from keystone.common.sql import migration_helpers
+
def upgrade(migrate_engine):
"""Replace API-version specific endpoint tables with one based on v3."""
@@ -26,7 +28,14 @@ def upgrade(migrate_engine):
legacy_table.drop()
new_table = sql.Table('endpoint_v3', meta, autoload=True)
- new_table.rename('endpoint')
+
+ renames = {'endpoint': new_table}
+ service_table = sql.Table('service', meta, autoload=True)
+ constraints = [{'table': new_table,
+ 'fk_column': 'service_id',
+ 'ref_column': service_table.c.id}]
+ migration_helpers.rename_tables_with_constraints(renames, constraints,
+ migrate_engine)
def downgrade(migrate_engine):
@@ -35,7 +44,14 @@ def downgrade(migrate_engine):
meta.bind = migrate_engine
new_table = sql.Table('endpoint', meta, autoload=True)
- new_table.rename('endpoint_v3')
+
+ renames = {'endpoint_v3': new_table}
+ service_table = sql.Table('service', meta, autoload=True)
+ constraints = [{'table': new_table,
+ 'fk_column': 'service_id',
+ 'ref_column': service_table.c.id}]
+ migration_helpers.rename_tables_with_constraints(renames, constraints,
+ migrate_engine)
sql.Table('service', meta, autoload=True)
legacy_table = sql.Table(
diff --git a/keystone/common/sql/migrate_repo/versions/015_tenant_to_project.py b/keystone/common/sql/migrate_repo/versions/015_tenant_to_project.py
index 5f276c68..2a63fad8 100644
--- a/keystone/common/sql/migrate_repo/versions/015_tenant_to_project.py
+++ b/keystone/common/sql/migrate_repo/versions/015_tenant_to_project.py
@@ -1,19 +1,66 @@
import sqlalchemy as sql
from sqlalchemy.orm import sessionmaker
+from keystone.common.sql import migration_helpers
+
+
+def rename_with_constraints(meta, legacy_project_table_name,
+ new_project_table_name,
+ legacy_user_project_membership_table_name,
+ new_user_project_membership_table_name):
+ # Not all RDBMSs support renaming a table that has foreign key constraints
+ # on it, so drop FK constraints before renaming and then replace FKs
+ # afterwards.
+
+ credential_table = sql.Table('credential', meta, autoload=True)
+ group_project_meta_table = sql.Table('group_project_metadata', meta,
+ autoload=True)
+ project_table = sql.Table(legacy_project_table_name, meta, autoload=True)
+ user_project_membership_table = sql.Table(
+ legacy_user_project_membership_table_name, meta, autoload=True)
+ user_table = sql.Table('user', meta, autoload=True)
+
+ constraints = [{'table': credential_table,
+ 'fk_column': 'project_id',
+ 'ref_column': project_table.c.id},
+ {'table': group_project_meta_table,
+ 'fk_column': 'project_id',
+ 'ref_column': project_table.c.id},
+ {'table': user_project_membership_table,
+ 'fk_column': 'tenant_id',
+ 'ref_column': project_table.c.id},
+ {'table': user_project_membership_table,
+ 'fk_column': 'user_id',
+ 'ref_column': user_table.c.id}]
+
+ renames = {
+ new_project_table_name: project_table,
+ new_user_project_membership_table_name: user_project_membership_table}
+
+ migration_helpers.rename_tables_with_constraints(renames, constraints,
+ meta.bind)
+
def upgrade_with_rename(meta, migrate_engine):
- legacy_table = sql.Table('tenant', meta, autoload=True)
- legacy_table.rename('project')
- legacy_table = sql.Table('user_tenant_membership', meta, autoload=True)
- legacy_table.rename('user_project_membership')
+ legacy_project_table_name = 'tenant'
+ new_project_table_name = 'project'
+ legacy_user_project_membership_table_name = 'user_tenant_membership'
+ new_user_project_membership_table_name = 'user_project_membership'
+ rename_with_constraints(meta, legacy_project_table_name,
+ new_project_table_name,
+ legacy_user_project_membership_table_name,
+ new_user_project_membership_table_name)
def downgrade_with_rename(meta, migrate_engine):
- upgrade_table = sql.Table('project', meta, autoload=True)
- upgrade_table.rename('tenant')
- upgrade_table = sql.Table('user_project_membership', meta, autoload=True)
- upgrade_table.rename('user_tenant_membership')
+ legacy_project_table_name = 'project'
+ new_project_table_name = 'tenant'
+ legacy_user_project_membership_table_name = 'user_project_membership'
+ new_user_project_membership_table_name = 'user_tenant_membership'
+ rename_with_constraints(meta, legacy_project_table_name,
+ new_project_table_name,
+ legacy_user_project_membership_table_name,
+ new_user_project_membership_table_name)
def upgrade_with_copy(meta, migrate_engine):
diff --git a/keystone/common/sql/migrate_repo/versions/016_normalize_domain_ids.py b/keystone/common/sql/migrate_repo/versions/016_normalize_domain_ids.py
index f8e46591..f28060e6 100644
--- a/keystone/common/sql/migrate_repo/versions/016_normalize_domain_ids.py
+++ b/keystone/common/sql/migrate_repo/versions/016_normalize_domain_ids.py
@@ -381,7 +381,9 @@ def downgrade_user_table_with_col_drop(meta, migrate_engine, session):
# Revert uniqueness settings for the name attribute
session.execute('ALTER TABLE "user" DROP CONSTRAINT '
'user_dom_name_unique;')
- session.execute('ALTER TABLE "user" ADD UNIQUE (name);')
+ # specify the constraint name so it can be referenced later
+ session.execute('ALTER TABLE "user" ADD CONSTRAINT user_name_key '
+ 'UNIQUE (name);')
session.commit()
# And now go ahead an drop the domain_id column
sql.Table('domain', meta, autoload=True)
diff --git a/keystone/common/sql/migrate_repo/versions/020_migrate_metadata_table_roles.py b/keystone/common/sql/migrate_repo/versions/020_migrate_metadata_table_roles.py
index 35110df4..a0c6ddbc 100644
--- a/keystone/common/sql/migrate_repo/versions/020_migrate_metadata_table_roles.py
+++ b/keystone/common/sql/migrate_repo/versions/020_migrate_metadata_table_roles.py
@@ -23,11 +23,9 @@ def upgrade(migrate_engine):
session = sql.orm.sessionmaker(bind=migrate_engine)()
for metadata in session.query(old_metadata_table):
+ data = json.loads(metadata.data)
if config.CONF.member_role_id not in metadata.data:
- data = json.loads(metadata.data)
data['roles'].append(config.CONF.member_role_id)
- else:
- data = metadata.data
r = session.query(new_metadata_table).filter_by(
user_id=metadata.user_id,
diff --git a/keystone/common/sql/migrate_repo/versions/027_set_engine_mysql_innodb.py b/keystone/common/sql/migrate_repo/versions/027_set_engine_mysql_innodb.py
new file mode 100644
index 00000000..ca8ccd08
--- /dev/null
+++ b/keystone/common/sql/migrate_repo/versions/027_set_engine_mysql_innodb.py
@@ -0,0 +1,143 @@
+
+import sqlalchemy as sql
+from sqlalchemy import MetaData
+
+from keystone.common.sql import migration_helpers
+
+
+def upgrade(migrate_engine):
+ # Upgrade operations go here. Don't create your own engine;
+ # bind migrate_engine to your metadata
+
+ if migrate_engine.name != 'mysql':
+ # InnoDB / MyISAM only applies to MySQL.
+ return
+
+ # This is a list of all the tables that might have been created with MyISAM
+ # rather than InnoDB.
+ tables = [
+ 'credential',
+ 'domain',
+ 'ec2_credential',
+ 'endpoint',
+ 'group',
+ 'group_domain_metadata',
+ 'group_project_metadata',
+ 'policy',
+ 'project',
+ 'role',
+ 'service',
+ 'token',
+ 'trust',
+ 'trust_role',
+ 'user',
+ 'user_domain_metadata',
+ 'user_group_membership',
+ 'user_project_metadata',
+ ]
+
+ meta = MetaData()
+ meta.bind = migrate_engine
+
+ domain_table = sql.Table('domain', meta, autoload=True)
+ endpoint_table = sql.Table('endpoint', meta, autoload=True)
+ group_table = sql.Table('group', meta, autoload=True)
+ group_domain_metadata_table = sql.Table('group_domain_metadata', meta,
+ autoload=True)
+ group_project_metadata_table = sql.Table('group_project_metadata', meta,
+ autoload=True)
+ project_table = sql.Table('project', meta, autoload=True)
+ service_table = sql.Table('service', meta, autoload=True)
+ user_table = sql.Table('user', meta, autoload=True)
+ user_domain_metadata_table = sql.Table('user_domain_metadata', meta,
+ autoload=True)
+ user_group_membership_table = sql.Table('user_group_membership', meta,
+ autoload=True)
+
+ # Mapping of table name to the constraints on that table,
+ # so we can create them.
+ table_constraints = {
+ 'endpoint': [{'table': endpoint_table,
+ 'fk_column': 'service_id',
+ 'ref_column': service_table.c.id},
+ ],
+ 'group': [{'table': group_table,
+ 'fk_column': 'domain_id',
+ 'ref_column': domain_table.c.id},
+ ],
+ 'group_domain_metadata': [{'table': group_domain_metadata_table,
+ 'fk_column': 'domain_id',
+ 'ref_column': domain_table.c.id},
+ ],
+ 'group_project_metadata': [{'table': group_project_metadata_table,
+ 'fk_column': 'project_id',
+ 'ref_column': project_table.c.id},
+ ],
+ 'project': [{'table': project_table,
+ 'fk_column': 'domain_id',
+ 'ref_column': domain_table.c.id},
+ ],
+ 'user': [{'table': user_table,
+ 'fk_column': 'domain_id',
+ 'ref_column': domain_table.c.id},
+ ],
+ 'user_domain_metadata': [{'table': user_domain_metadata_table,
+ 'fk_column': 'domain_id',
+ 'ref_column': domain_table.c.id},
+ ],
+ 'user_group_membership': [{'table': user_group_membership_table,
+ 'fk_column': 'user_id',
+ 'ref_column': user_table.c.id},
+ {'table': user_group_membership_table,
+ 'fk_column': 'group_id',
+ 'ref_column': group_table.c.id},
+ ],
+ 'user_project_metadata': [{'table': group_project_metadata_table,
+ 'fk_column': 'project_id',
+ 'ref_column': project_table.c.id},
+ ],
+ }
+
+ # Maps a table name to the tables that reference it as a FK constraint
+ # (See the map above).
+ ref_tables_map = {
+ 'service': ['endpoint', ],
+ 'domain': ['group', 'group_domain_metadata', 'project', 'user',
+ 'user_domain_metadata', ],
+ 'project': ['group_project_metadata', 'user_project_metadata', ],
+ 'user': ['user_group_membership', ],
+ 'group': ['user_group_membership', ],
+ }
+
+ # The names of tables that need to have their FKs added.
+ fk_table_names = set()
+
+ d = migrate_engine.execute("SHOW TABLE STATUS WHERE Engine!='InnoDB';")
+ for row in d.fetchall():
+ table_name = row[0]
+
+ if table_name not in tables:
+ # Skip this table since it's not a Keystone table.
+ continue
+
+ migrate_engine.execute("ALTER TABLE `%s` Engine=InnoDB" % table_name)
+
+ # Will add the FKs to the table if any of
+ # a) the table itself was converted
+ # b) the tables that the table referenced were converted
+
+ if table_name in table_constraints:
+ fk_table_names.add(table_name)
+
+ ref_tables = ref_tables_map.get(table_name, [])
+ for other_table_name in ref_tables:
+ fk_table_names.add(other_table_name)
+
+ # Now add all the FK constraints to those tables
+ for table_name in fk_table_names:
+ constraints = table_constraints.get(table_name)
+ migration_helpers.add_constraints(constraints)
+
+
+def downgrade(migrate_engine):
+ pass
diff --git a/keystone/common/sql/migrate_repo/versions/028_fixup_group_metadata.py b/keystone/common/sql/migrate_repo/versions/028_fixup_group_metadata.py
new file mode 100644
index 00000000..66055a99
--- /dev/null
+++ b/keystone/common/sql/migrate_repo/versions/028_fixup_group_metadata.py
@@ -0,0 +1,190 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 OpenStack LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import sqlalchemy as sql
+
+
+def upgrade(migrate_engine):
+ # The group_project_metadata table was not updated in terms of its
+ # FK to the tenant table when the tenant->project change was made at
+ # the 015 migration for sqlite. This upgrade fixes that.
+ # We need to create a fake tenant table so that we can first load
+ # the group_project_metadata at all, then do a dance of copying tables
+ # to get us to the correct schema.
+ meta = sql.MetaData()
+ meta.bind = migrate_engine
+
+ if migrate_engine.name != 'sqlite':
+ return
+
+ temp_tenant_table = sql.Table(
+ 'tenant',
+ meta,
+ sql.Column('id', sql.String(64), primary_key=True))
+ temp_tenant_table.create(migrate_engine, checkfirst=True)
+
+ sql.Table('user', meta, autoload=True)
+ old_group_metadata_table = sql.Table('group_project_metadata',
+ meta, autoload=True)
+
+ # OK, we now have the table loaded, create a first
+ # temporary table of a different name with the correct FK
+ sql.Table('project', meta, autoload=True)
+ temp_group_project_metadata_table = sql.Table(
+ 'temp_group_project_metadata',
+ meta,
+ sql.Column(
+ 'group_id',
+ sql.String(64),
+ primary_key=True),
+ sql.Column(
+ 'project_id',
+ sql.String(64),
+ sql.ForeignKey('project.id'),
+ primary_key=True),
+ sql.Column('data', sql.Text()))
+ temp_group_project_metadata_table.create(migrate_engine, checkfirst=True)
+
+ # Populate the new temporary table, and then drop the old one
+ session = sql.orm.sessionmaker(bind=migrate_engine)()
+
+ for metadata in session.query(old_group_metadata_table):
+ q = temp_group_project_metadata_table.insert().values(
+ group_id=metadata.group_id,
+ project_id=metadata.project_id,
+ data=metadata.data)
+ session.execute(q)
+ session.commit()
+ old_group_metadata_table.drop()
+ temp_tenant_table.drop()
+
+ # Now do a final table copy to get the table of the right name.
+ # Re-init the metadata so that sqlalchemy does not get confused with
+ # multiple versions of the same named table.
+ meta2 = sql.MetaData()
+ meta2.bind = migrate_engine
+
+ sql.Table('project', meta2, autoload=True)
+ new_group_project_metadata_table = sql.Table(
+ 'group_project_metadata',
+ meta2,
+ sql.Column(
+ 'group_id',
+ sql.String(64),
+ primary_key=True),
+ sql.Column(
+ 'project_id',
+ sql.String(64),
+ sql.ForeignKey('project.id'),
+ primary_key=True),
+ sql.Column('data', sql.Text()))
+ new_group_project_metadata_table.create(migrate_engine, checkfirst=True)
+
+ for metadata in session.query(temp_group_project_metadata_table):
+ q = new_group_project_metadata_table.insert().values(
+ group_id=metadata.group_id,
+ project_id=metadata.project_id,
+ data=metadata.data)
+ session.execute(q)
+ session.commit()
+
+ temp_group_project_metadata_table.drop()
+
+
+def downgrade(migrate_engine):
+ # Put the group_project_metadata table back the way it was in its rather
+ # broken state. We don't try and re-write history, since otherwise people
+ # get out of step.
+ meta = sql.MetaData()
+ meta.bind = migrate_engine
+
+ if migrate_engine.name != 'sqlite':
+ return
+
+ sql.Table('user', meta, autoload=True)
+ sql.Table('project', meta, autoload=True)
+ group_metadata_table = sql.Table('group_project_metadata',
+ meta, autoload=True)
+
+ # We want to create a temp group meta table with the FK
+ # set to the wrong place.
+ temp_tenant_table = sql.Table(
+ 'tenant',
+ meta,
+ sql.Column('id', sql.String(64), primary_key=True))
+ temp_tenant_table.create(migrate_engine, checkfirst=True)
+
+ temp_group_project_metadata_table = sql.Table(
+ 'temp_group_project_metadata',
+ meta,
+ sql.Column(
+ 'group_id',
+ sql.String(64),
+ primary_key=True),
+ sql.Column(
+ 'project_id',
+ sql.String(64),
+ sql.ForeignKey('tenant.id'),
+ primary_key=True),
+ sql.Column('data', sql.Text()))
+ temp_group_project_metadata_table.create(migrate_engine, checkfirst=True)
+
+ # Now populate the temp table and drop the real one
+ session = sql.orm.sessionmaker(bind=migrate_engine)()
+
+ for metadata in session.query(group_metadata_table):
+ q = temp_group_project_metadata_table.insert().values(
+ group_id=metadata.group_id,
+ project_id=metadata.project_id,
+ data=metadata.data)
+ session.execute(q)
+
+ session.commit()
+ group_metadata_table.drop()
+
+ # Now copy again into the correctly named table. Re-init the metadata
+ # so that sqlalchemy does not get confused with multiple versions of the
+ # same named table.
+ meta2 = sql.MetaData()
+ meta2.bind = migrate_engine
+
+ sql.Table('tenant', meta2, autoload=True)
+ new_group_project_metadata_table = sql.Table(
+ 'group_project_metadata',
+ meta2,
+ sql.Column(
+ 'group_id',
+ sql.String(64),
+ primary_key=True),
+ sql.Column(
+ 'project_id',
+ sql.String(64),
+ sql.ForeignKey('tenant.id'),
+ primary_key=True),
+ sql.Column('data', sql.Text()))
+ new_group_project_metadata_table.create(migrate_engine, checkfirst=True)
+
+ for metadata in session.query(temp_group_project_metadata_table):
+ q = new_group_project_metadata_table.insert().values(
+ group_id=metadata.group_id,
+ project_id=metadata.project_id,
+ data=metadata.data)
+ session.execute(q)
+
+ session.commit()
+
+ temp_group_project_metadata_table.drop()
+ temp_tenant_table.drop()
diff --git a/keystone/common/sql/migrate_repo/versions/029_update_assignment_metadata.py b/keystone/common/sql/migrate_repo/versions/029_update_assignment_metadata.py
new file mode 100644
index 00000000..a9276804
--- /dev/null
+++ b/keystone/common/sql/migrate_repo/versions/029_update_assignment_metadata.py
@@ -0,0 +1,102 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 OpenStack LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import json
+
+import sqlalchemy as sql
+
+
+def build_update(table_name, upgrade_table, row, values):
+ if table_name == 'user_project_metadata':
+ update = upgrade_table.update().where(
+ upgrade_table.c.user_id == row.user_id).where(
+ upgrade_table.c.project_id == row.project_id).values(values)
+ elif table_name == 'group_project_metadata':
+ update = upgrade_table.update().where(
+ upgrade_table.c.group_id == row.group_id).where(
+ upgrade_table.c.project_id == row.project_id).values(values)
+ elif table_name == 'user_domain_metadata':
+ update = upgrade_table.update().where(
+ upgrade_table.c.user_id == row.user_id).where(
+ upgrade_table.c.domain_id == row.domain_id).values(values)
+ else:
+ update = upgrade_table.update().where(
+ upgrade_table.c.group_id == row.group_id).where(
+ upgrade_table.c.domain_id == row.domain_id).values(values)
+ return update
+
+
+def upgrade_grant_table(meta, migrate_engine, session, table_name):
+
+ # Convert the roles component of the metadata from a list
+ # of ids to a list of dicts
+
+ def list_to_dict_list(metadata):
+ json_metadata = json.loads(metadata)
+ if 'roles' in json_metadata:
+ json_metadata['roles'] = (
+ [{'id': x} for x in json_metadata['roles']])
+ return json.dumps(json_metadata)
+
+ upgrade_table = sql.Table(table_name, meta, autoload=True)
+ for assignment in session.query(upgrade_table):
+ values = {'data': list_to_dict_list(assignment.data)}
+ update = build_update(table_name, upgrade_table, assignment, values)
+ migrate_engine.execute(update)
+
+
+def downgrade_grant_table(meta, migrate_engine, session, table_name):
+
+ # Convert the roles component of the metadata from a list
+ # of dicts to a simple list of ids. Any inherited roles are deleted
+ # since they would have no meaning
+
+ def dict_list_to_list(metadata):
+ json_metadata = json.loads(metadata)
+ if 'roles' in json_metadata:
+ json_metadata['roles'] = ([x['id'] for x in json_metadata['roles']
+ if 'inherited_to' not in x])
+ return json.dumps(json_metadata)
+
+ downgrade_table = sql.Table(table_name, meta, autoload=True)
+ for assignment in session.query(downgrade_table):
+ values = {'data': dict_list_to_list(assignment.data)}
+ update = build_update(table_name, downgrade_table, assignment, values)
+ migrate_engine.execute(update)
+
+
+def upgrade(migrate_engine):
+ meta = sql.MetaData()
+ meta.bind = migrate_engine
+ session = sql.orm.sessionmaker(bind=migrate_engine)()
+
+ for grant_table in ['user_project_metadata', 'user_domain_metadata',
+ 'group_project_metadata', 'group_domain_metadata']:
+ upgrade_grant_table(meta, migrate_engine, session, grant_table)
+ session.commit()
+ session.close()
+
+
+def downgrade(migrate_engine):
+ meta = sql.MetaData()
+ meta.bind = migrate_engine
+ session = sql.orm.sessionmaker(bind=migrate_engine)()
+
+ for grant_table in ['user_project_metadata', 'user_domain_metadata',
+ 'group_project_metadata', 'group_domain_metadata']:
+ downgrade_grant_table(meta, migrate_engine, session, grant_table)
+ session.commit()
+ session.close()
diff --git a/keystone/common/sql/migrate_repo/versions/030_drop_credential_constraint_sqlite.py b/keystone/common/sql/migrate_repo/versions/030_drop_credential_constraint_sqlite.py
new file mode 100644
index 00000000..27676dcc
--- /dev/null
+++ b/keystone/common/sql/migrate_repo/versions/030_drop_credential_constraint_sqlite.py
@@ -0,0 +1,119 @@
+
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 OpenStack LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import sqlalchemy
+from sqlalchemy.orm import sessionmaker
+
+
+def upgrade(migrate_engine):
+ if migrate_engine.name == 'sqlite':
+ drop_credential_table_foreign_key_constraints_for_sqlite(
+ migrate_engine)
+
+
+def downgrade(migrate_engine):
+ if migrate_engine.name == 'sqlite':
+ add_credential_table_foreign_key_constraints_for_sqlite(migrate_engine)
+
+
+def drop_credential_table_foreign_key_constraints_for_sqlite(migrate_engine):
+ meta = sqlalchemy.MetaData()
+ meta.bind = migrate_engine
+
+ # NOTE(nachiappan): SQLite does not support ALTER TABLE DROP constraint.
+ # So we need to move the data to new credenital table
+ # created without constraints, drop the old table and
+ # rename the new table to credential.
+ sqlalchemy.Table('user', meta, autoload=True)
+ tenant_table = sqlalchemy.Table(
+ 'tenant',
+ meta,
+ sqlalchemy.Column('id', sqlalchemy.String(64), primary_key=True),
+ sqlalchemy.Column(
+ 'name', sqlalchemy.String(64), unique=True, nullable=False),
+ sqlalchemy.Column('extra', sqlalchemy.Text()))
+ tenant_table.create(migrate_engine, checkfirst=True)
+ cred_table = sqlalchemy.Table('credential', meta, autoload=True)
+
+ session = sessionmaker(bind=migrate_engine)()
+ new_credential_table = sqlalchemy.Table(
+ 'new_credential',
+ meta,
+ sqlalchemy.Column('id', sqlalchemy.String(64), primary_key=True),
+ sqlalchemy.Column('user_id',
+ sqlalchemy.String(64),
+ nullable=False),
+ sqlalchemy.Column('project_id',
+ sqlalchemy.String(64)),
+ sqlalchemy.Column('blob', sqlalchemy.Text(), nullable=False),
+ sqlalchemy.Column('type', sqlalchemy.String(255), nullable=False),
+ sqlalchemy.Column('extra', sqlalchemy.Text()))
+ new_credential_table.create(migrate_engine, checkfirst=True)
+
+ insert = new_credential_table.insert()
+ for credential in session.query(cred_table):
+ insert.execute({'id': credential.id,
+ 'user_id': credential.user_id,
+ 'project_id': credential.project_id,
+ 'blob': credential.blob,
+ 'type': credential.type,
+ 'extra': credential.extra})
+ cred_table.drop()
+ tenant_table.drop()
+ new_credential_table.rename('credential')
+ session.commit()
+ session.close()
+
+
+def add_credential_table_foreign_key_constraints_for_sqlite(migrate_engine):
+ meta = sqlalchemy.MetaData()
+ meta.bind = migrate_engine
+
+ cred_table = sqlalchemy.Table('credential', meta, autoload=True)
+ sqlalchemy.Table('user', meta, autoload=True)
+
+ session = sessionmaker(bind=migrate_engine)()
+ old_credential_table = sqlalchemy.Table(
+ 'old_credential',
+ meta,
+ sqlalchemy.Column('id', sqlalchemy.String(64), primary_key=True),
+ sqlalchemy.Column('user_id',
+ sqlalchemy.String(64),
+ sqlalchemy.ForeignKey('user.id'),
+ nullable=False),
+ # NOTE(nachiappan): Not creating the foreign key constraint with
+ # project table as version 15 conflicts with
+ # version 7.
+ sqlalchemy.Column('project_id',
+ sqlalchemy.String(64)),
+ sqlalchemy.Column('blob', sqlalchemy.Text(), nullable=False),
+ sqlalchemy.Column('type', sqlalchemy.String(255), nullable=False),
+ sqlalchemy.Column('extra', sqlalchemy.Text()))
+ old_credential_table.create(migrate_engine, checkfirst=True)
+
+ insert = old_credential_table.insert()
+ for credential in session.query(cred_table):
+ insert.execute({'id': credential.id,
+ 'user_id': credential.user_id,
+ 'project_id': credential.project_id,
+ 'blob': credential.blob,
+ 'type': credential.type,
+ 'extra': credential.extra})
+ cred_table.drop()
+ old_credential_table.rename('credential')
+ session.commit()
+ session.close()
diff --git a/keystone/common/sql/migration_helpers.py b/keystone/common/sql/migration_helpers.py
index 6823b6a7..8a581924 100644
--- a/keystone/common/sql/migration_helpers.py
+++ b/keystone/common/sql/migration_helpers.py
@@ -52,7 +52,44 @@ def remove_constraints(constraints):
def add_constraints(constraints):
for constraint_def in constraints:
+
+ if constraint_def['table'].kwargs.get('mysql_engine') == 'MyISAM':
+ # Don't try to create constraint when using MyISAM because it's
+ # not supported.
+ continue
+
+ ref_col = constraint_def['ref_column']
+ ref_engine = ref_col.table.kwargs.get('mysql_engine')
+ if ref_engine == 'MyISAM':
+ # Don't try to create constraint when using MyISAM because it's
+ # not supported.
+ continue
+
migrate.ForeignKeyConstraint(
columns=[getattr(constraint_def['table'].c,
constraint_def['fk_column'])],
refcolumns=[constraint_def['ref_column']]).create()
+
+
+def rename_tables_with_constraints(renames, constraints, engine):
+ """Renames tables with foreign key constraints.
+
+ Tables are renamed after first removing constraints. The constraints are
+ replaced after the rename is complete.
+
+ This works on databases that don't support renaming tables that have
+ constraints on them (DB2).
+
+ `renames` is a dict, mapping {'to_table_name': from_table, ...}
+ """
+
+ if engine.name != 'sqlite':
+ # Sqlite doesn't support constraints, so nothing to remove.
+ remove_constraints(constraints)
+
+ for to_table_name in renames:
+ from_table = renames[to_table_name]
+ from_table.rename(to_table_name)
+
+ if engine != 'sqlite':
+ add_constraints(constraints)
diff --git a/keystone/common/sql/nova.py b/keystone/common/sql/nova.py
index c6d452cd..fd8d2481 100644
--- a/keystone/common/sql/nova.py
+++ b/keystone/common/sql/nova.py
@@ -18,10 +18,11 @@
import uuid
+from keystone import assignment
from keystone.common import logging
from keystone import config
from keystone.contrib.ec2.backends import sql as ec2_sql
-from keystone.identity.backends import sql as identity_sql
+from keystone import identity
LOG = logging.getLogger(__name__)
@@ -30,18 +31,20 @@ DEFAULT_DOMAIN_ID = CONF.identity.default_domain_id
def import_auth(data):
- identity_api = identity_sql.Identity()
- tenant_map = _create_projects(identity_api, data['tenants'])
+ identity_api = identity.Manager()
+ assignment_api = assignment.Manager()
+
+ tenant_map = _create_projects(assignment_api, data['tenants'])
user_map = _create_users(identity_api, data['users'])
- _create_memberships(identity_api, data['user_tenant_list'],
+ _create_memberships(assignment_api, data['user_tenant_list'],
user_map, tenant_map)
- role_map = _create_roles(identity_api, data['roles'])
- _assign_roles(identity_api, data['role_user_tenant_list'],
+ role_map = _create_roles(assignment_api, data['roles'])
+ _assign_roles(assignment_api, data['role_user_tenant_list'],
role_map, user_map, tenant_map)
ec2_api = ec2_sql.Ec2()
ec2_creds = data['ec2_credentials']
- _create_ec2_creds(ec2_api, identity_api, ec2_creds, user_map)
+ _create_ec2_creds(ec2_api, assignment_api, ec2_creds, user_map)
def _generate_uuid():
@@ -120,10 +123,10 @@ def _assign_roles(api, assignments, role_map, user_map, tenant_map):
api.add_role_to_user_and_project(user_id, tenant_id, role_id)
-def _create_ec2_creds(ec2_api, identity_api, ec2_creds, user_map):
+def _create_ec2_creds(ec2_api, assignment_api, ec2_creds, user_map):
for ec2_cred in ec2_creds:
user_id = user_map[ec2_cred['user_id']]
- for tenant_id in identity_api.get_projects_for_user(user_id):
+ for tenant_id in assignment_api.get_projects_for_user(user_id):
cred_dict = {
'access': '%s:%s' % (tenant_id, ec2_cred['access_key']),
'secret': ec2_cred['secret_key'],
diff --git a/keystone/common/sql/util.py b/keystone/common/sql/util.py
deleted file mode 100644
index c31e50c0..00000000
--- a/keystone/common/sql/util.py
+++ /dev/null
@@ -1,42 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2012 OpenStack LLC
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import os
-import shutil
-
-from keystone.common.sql import core
-from keystone.common.sql import migration
-from keystone import config
-
-
-CONF = config.CONF
-
-
-def setup_test_database():
- try:
- if os.path.exists('test.db'):
- os.unlink('test.db')
- if not os.path.exists('test.db.pristine'):
- migration.db_sync()
- shutil.copyfile('test.db', 'test.db.pristine')
- else:
- shutil.copyfile('test.db.pristine', 'test.db')
- except Exception:
- pass
-
-
-def teardown_test_database():
- core.set_global_engine(None)
diff --git a/keystone/common/wsgi.py b/keystone/common/wsgi.py
index 5143db6e..f47cde13 100644
--- a/keystone/common/wsgi.py
+++ b/keystone/common/wsgi.py
@@ -73,6 +73,55 @@ def mask_password(message, is_unicode=False, secret="***"):
return result
+def validate_token_bind(context, token_ref):
+ bind_mode = CONF.token.enforce_token_bind
+
+ if bind_mode == 'disabled':
+ return
+
+ bind = token_ref.get('bind', {})
+
+ # permissive and strict modes don't require there to be a bind
+ permissive = bind_mode in ('permissive', 'strict')
+
+ # get the named mode if bind_mode is not one of the known
+ name = None if permissive or bind_mode == 'required' else bind_mode
+
+ if not bind:
+ if permissive:
+ # no bind provided and none required
+ return
+ else:
+ LOG.info(_("No bind information present in token"))
+ raise exception.Unauthorized()
+
+ if name and name not in bind:
+ LOG.info(_("Named bind mode %s not in bind information"), name)
+ raise exception.Unauthorized()
+
+ for bind_type, identifier in bind.iteritems():
+ if bind_type == 'kerberos':
+ if not context.get('AUTH_TYPE', '').lower() == 'negotiate':
+ LOG.info(_("Kerberos credentials required and not present"))
+ raise exception.Unauthorized()
+
+ if not context.get('REMOTE_USER') == identifier:
+ LOG.info(_("Kerberos credentials do not match those in bind"))
+ raise exception.Unauthorized()
+
+ LOG.info(_("Kerberos bind authentication successful"))
+
+ elif bind_mode == 'permissive':
+ LOG.debug(_("Ignoring unknown bind for permissive mode: "
+ "{%(bind_type)s: %(identifier)s}"),
+ {'bind_type': bind_type, 'identifier': identifier})
+ else:
+ LOG.info(_("Couldn't verify unknown bind: "
+ "{%(bind_type)s: %(identifier)s}"),
+ {'bind_type': bind_type, 'identifier': identifier})
+ raise exception.Unauthorized()
+
+
class WritableLogger(object):
"""A thin wrapper that responds to `write` and logs."""
@@ -103,18 +152,18 @@ class BaseApplication(object):
[app:wadl]
latest_version = 1.3
- paste.app_factory = nova.api.fancy_api:Wadl.factory
+ paste.app_factory = keystone.fancy_api:Wadl.factory
which would result in a call to the `Wadl` class as
- import nova.api.fancy_api
- fancy_api.Wadl(latest_version='1.3')
+ import keystone.fancy_api
+ keystone.fancy_api.Wadl(latest_version='1.3')
You could of course re-implement the `factory` method in subclasses,
but using the kwarg passing it shouldn't be necessary.
"""
- return cls()
+ return cls(**local_config)
def __call__(self, environ, start_response):
r"""Subclasses will probably want to implement __call__ like this:
@@ -154,7 +203,7 @@ class BaseApplication(object):
class Application(BaseApplication):
- @webob.dec.wsgify
+ @webob.dec.wsgify(RequestClass=Request)
def __call__(self, req):
arg_dict = req.environ['wsgiorg.routing_args'][1]
action = arg_dict.pop('action')
@@ -167,12 +216,20 @@ class Application(BaseApplication):
context['headers'] = dict(req.headers.iteritems())
context['path'] = req.environ['PATH_INFO']
params = req.environ.get(PARAMS_ENV, {})
- if 'REMOTE_USER' in req.environ:
- context['REMOTE_USER'] = req.environ['REMOTE_USER']
- elif context.get('REMOTE_USER', None) is not None:
- del context['REMOTE_USER']
+
+ for name in ['REMOTE_USER', 'AUTH_TYPE']:
+ try:
+ context[name] = req.environ[name]
+ except KeyError:
+ try:
+ del context[name]
+ except KeyError:
+ pass
+
params.update(arg_dict)
+ context.setdefault('is_admin', False)
+
# TODO(termie): do some basic normalization on methods
method = getattr(self, action)
@@ -226,11 +283,11 @@ class Application(BaseApplication):
def assert_admin(self, context):
if not context['is_admin']:
try:
- user_token_ref = self.token_api.get_token(
- token_id=context['token_id'])
+ user_token_ref = self.token_api.get_token(context['token_id'])
except exception.TokenNotFound as e:
raise exception.Unauthorized(e)
+ validate_token_bind(context, user_token_ref)
creds = user_token_ref['metadata'].copy()
try:
@@ -274,12 +331,12 @@ class Middleware(Application):
[filter:analytics]
redis_host = 127.0.0.1
- paste.filter_factory = nova.api.analytics:Analytics.factory
+ paste.filter_factory = keystone.analytics:Analytics.factory
which would result in a call to the `Analytics` class as
- import nova.api.analytics
- analytics.Analytics(app_from_paste, redis_host='127.0.0.1')
+ import keystone.analytics
+ keystone.analytics.Analytics(app, redis_host='127.0.0.1')
You could of course re-implement the `factory` method in subclasses,
but using the kwarg passing it shouldn't be necessary.
@@ -484,12 +541,12 @@ class ExtensionRouter(Router):
[filter:analytics]
redis_host = 127.0.0.1
- paste.filter_factory = nova.api.analytics:Analytics.factory
+ paste.filter_factory = keystone.analytics:Analytics.factory
which would result in a call to the `Analytics` class as
- import nova.api.analytics
- analytics.Analytics(app_from_paste, redis_host='127.0.0.1')
+ import keystone.analytics
+ keystone.analytics.Analytics(app, redis_host='127.0.0.1')
You could of course re-implement the `factory` method in subclasses,
but using the kwarg passing it shouldn't be necessary.
@@ -498,7 +555,7 @@ class ExtensionRouter(Router):
def _factory(app):
conf = global_config.copy()
conf.update(local_config)
- return cls(app)
+ return cls(app, **local_config)
return _factory
@@ -525,7 +582,7 @@ def render_exception(error):
body = {'error': {
'code': error.code,
'title': error.title,
- 'message': str(error)
+ 'message': unicode(error)
}}
if isinstance(error, exception.AuthPluginException):
body['error']['identity'] = error.authentication
diff --git a/keystone/contrib/admin_crud/core.py b/keystone/contrib/admin_crud/core.py
index c06afcf7..f98397ae 100644
--- a/keystone/contrib/admin_crud/core.py
+++ b/keystone/contrib/admin_crud/core.py
@@ -14,10 +14,31 @@
# License for the specific language governing permissions and limitations
# under the License.
from keystone import catalog
+from keystone.common import extension
from keystone.common import wsgi
from keystone import identity
+extension.register_admin_extension(
+ 'OS-KSADM', {
+ 'name': 'OpenStack Keystone Admin',
+ 'namespace': 'http://docs.openstack.org/identity/api/ext/'
+ 'OS-KSADM/v1.0',
+ 'alias': 'OS-KSADM',
+ 'updated': '2013-07-11T17:14:00-00:00',
+ 'description': 'OpenStack extensions to Keystone v2.0 API '
+ 'enabling Administrative Operations.',
+ 'links': [
+ {
+ 'rel': 'describedby',
+ # TODO(dolph): link needs to be revised after
+ # bug 928059 merges
+ 'type': 'text/html',
+ 'href': 'https://github.com/openstack/identity-api',
+ }
+ ]})
+
+
class CrudExtension(wsgi.ExtensionRouter):
"""Previously known as the OS-KSADM extension.
diff --git a/keystone/contrib/ec2/core.py b/keystone/contrib/ec2/core.py
index e8471ec6..8f72e431 100644
--- a/keystone/contrib/ec2/core.py
+++ b/keystone/contrib/ec2/core.py
@@ -40,6 +40,7 @@ from keystoneclient.contrib.ec2 import utils as ec2_utils
from keystone.common import controller
from keystone.common import dependency
+from keystone.common import extension
from keystone.common import manager
from keystone.common import utils
from keystone.common import wsgi
@@ -51,6 +52,25 @@ from keystone import token
CONF = config.CONF
+EXTENSION_DATA = {
+ 'name': 'OpenStack EC2 API',
+ 'namespace': 'http://docs.openstack.org/identity/api/ext/'
+ 'OS-EC2/v1.0',
+ 'alias': 'OS-EC2',
+ 'updated': '2013-07-07T12:00:0-00:00',
+ 'description': 'OpenStack EC2 Credentials backend.',
+ 'links': [
+ {
+ 'rel': 'describedby',
+ # TODO(ayoung): needs a description
+ 'type': 'text/html',
+ 'href': 'https://github.com/openstack/identity-api',
+ }
+ ]}
+extension.register_admin_extension(EXTENSION_DATA['alias'], EXTENSION_DATA)
+extension.register_public_extension(EXTENSION_DATA['alias'], EXTENSION_DATA)
+
+
@dependency.provider('ec2_api')
class Manager(manager.Manager):
"""Default pivot point for the EC2 Credentials backend.
@@ -97,7 +117,7 @@ class Ec2Extension(wsgi.ExtensionRouter):
conditions=dict(method=['DELETE']))
-@dependency.requires('catalog_api', 'ec2_api')
+@dependency.requires('catalog_api', 'ec2_api', 'token_provider_api')
class Ec2Controller(controller.V2Controller):
def check_signature(self, creds_ref, credentials):
signer = ec2_utils.Ec2Signer(creds_ref['secret'])
@@ -153,16 +173,14 @@ class Ec2Controller(controller.V2Controller):
token_id = uuid.uuid4().hex
tenant_ref = self.identity_api.get_project(creds_ref['tenant_id'])
user_ref = self.identity_api.get_user(creds_ref['user_id'])
- metadata_ref = self.identity_api.get_metadata(
- user_id=user_ref['id'],
- tenant_id=tenant_ref['id'])
+ metadata_ref = {}
+ metadata_ref['roles'] = (
+ self.identity_api.get_roles_for_user_and_project(
+ user_ref['id'], tenant_ref['id']))
# Validate that the auth info is valid and nothing is disabled
token.validate_auth_info(self, user_ref, tenant_ref)
- # TODO(termie): optimize this call at some point and put it into the
- # the return for metadata
- # fill out the roles in the metadata
roles = metadata_ref.get('roles', [])
if not roles:
raise exception.Unauthorized(message='User not valid for tenant.')
@@ -170,21 +188,18 @@ class Ec2Controller(controller.V2Controller):
for role_id in roles]
catalog_ref = self.catalog_api.get_catalog(
- user_id=user_ref['id'],
- tenant_id=tenant_ref['id'],
- metadata=metadata_ref)
-
- token_ref = self.token_api.create_token(
- token_id, dict(id=token_id,
- user=user_ref,
- tenant=tenant_ref,
- metadata=metadata_ref))
-
- # TODO(termie): i don't think the ec2 middleware currently expects a
- # full return, but it contains a note saying that it
- # would be better to expect a full return
- return token.controllers.Auth.format_authenticate(
- token_ref, roles_ref, catalog_ref)
+ user_ref['id'], tenant_ref['id'], metadata_ref)
+
+ auth_token_data = dict(user=user_ref,
+ tenant=tenant_ref,
+ metadata=metadata_ref,
+ id='placeholder')
+ (token_id, token_data) = self.token_provider_api.issue_token(
+ version=token.provider.V2,
+ token_ref=auth_token_data,
+ roles_ref=roles_ref,
+ catalog_ref=catalog_ref)
+ return token_data
def create_credential(self, context, user_id, tenant_id):
"""Create a secret/access pair for use with ec2 style auth.
diff --git a/keystone/contrib/s3/core.py b/keystone/contrib/s3/core.py
index 44b038d4..29ea4fe2 100644
--- a/keystone/contrib/s3/core.py
+++ b/keystone/contrib/s3/core.py
@@ -27,6 +27,7 @@ import base64
import hashlib
import hmac
+from keystone.common import extension
from keystone.common import utils
from keystone.common import wsgi
from keystone import config
@@ -35,6 +36,23 @@ from keystone import exception
CONF = config.CONF
+EXTENSION_DATA = {
+ 'name': 'OpenStack S3 API',
+ 'namespace': 'http://docs.openstack.org/identity/api/ext/'
+ 's3tokens/v1.0',
+ 'alias': 's3tokens',
+ 'updated': '2013-07-07T12:00:0-00:00',
+ 'description': 'OpenStack S3 API.',
+ 'links': [
+ {
+ 'rel': 'describedby',
+ # TODO(ayoung): needs a description
+ 'type': 'text/html',
+ 'href': 'https://github.com/openstack/identity-api',
+ }
+ ]}
+extension.register_admin_extension(EXTENSION_DATA['alias'], EXTENSION_DATA)
+
class S3Extension(wsgi.ExtensionRouter):
def add_routes(self, mapper):
diff --git a/keystone/contrib/stats/core.py b/keystone/contrib/stats/core.py
index 0325c4fa..1d7b2cdf 100644
--- a/keystone/contrib/stats/core.py
+++ b/keystone/contrib/stats/core.py
@@ -14,6 +14,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+from keystone.common import extension
from keystone.common import logging
from keystone.common import manager
from keystone.common import wsgi
@@ -27,6 +28,23 @@ from keystone import token
CONF = config.CONF
LOG = logging.getLogger(__name__)
+extension_data = {
+ 'name': 'Openstack Keystone Stats API',
+ 'namespace': 'http://docs.openstack.org/identity/api/ext/'
+ 'OS-STATS/v1.0',
+ 'alias': 'OS-STATS',
+ 'updated': '2013-07-07T12:00:0-00:00',
+ 'description': 'Openstack Keystone Stats API.',
+ 'links': [
+ {
+ 'rel': 'describedby',
+ # TODO(ayoung): needs a description
+ 'type': 'text/html',
+ 'href': 'https://github.com/openstack/identity-api',
+ }
+ ]}
+extension.register_admin_extension(extension_data['alias'], extension_data)
+
class Manager(manager.Manager):
"""Default pivot point for the Stats backend.
diff --git a/keystone/contrib/user_crud/core.py b/keystone/contrib/user_crud/core.py
index 79144ae5..f9f09b89 100644
--- a/keystone/contrib/user_crud/core.py
+++ b/keystone/contrib/user_crud/core.py
@@ -17,6 +17,7 @@
import copy
import uuid
+from keystone.common import extension
from keystone.common import logging
from keystone.common import wsgi
from keystone import exception
@@ -26,6 +27,25 @@ from keystone import identity
LOG = logging.getLogger(__name__)
+extension.register_public_extension(
+ 'OS-KSCRUD', {
+ 'name': 'OpenStack Keystone User CRUD',
+ 'namespace': 'http://docs.openstack.org/identity/api/ext/'
+ 'OS-KSCRUD/v1.0',
+ 'alias': 'OS-KSCRUD',
+ 'updated': '2013-07-07T12:00:0-00:00',
+ 'description': 'OpenStack extensions to Keystone v2.0 API '
+ 'enabling User Operations.',
+ 'links': [
+ {
+ 'rel': 'describedby',
+ # TODO(ayoung): needs a description
+ 'type': 'text/html',
+ 'href': 'https://github.com/openstack/identity-api',
+ }
+ ]})
+
+
class UserController(identity.controllers.User):
def set_user_password(self, context, user_id, user):
token_id = context.get('token_id')
@@ -43,7 +63,7 @@ class UserController(identity.controllers.User):
try:
user_ref = self.identity_api.authenticate(
user_id=user_id_from_token,
- password=original_password)[0]
+ password=original_password)
if not user_ref.get('enabled', True):
# NOTE(dolph): why can't you set a disabled user's password?
raise exception.Unauthorized('User is disabled')
diff --git a/keystone/controllers.py b/keystone/controllers.py
index 6dd303e1..8ffa073a 100644
--- a/keystone/controllers.py
+++ b/keystone/controllers.py
@@ -14,6 +14,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+from keystone.common import extension
from keystone.common import logging
from keystone.common import wsgi
from keystone import config
@@ -32,10 +33,10 @@ _VERSIONS = []
class Extensions(wsgi.Application):
"""Base extensions controller to be extended by public and admin API's."""
- def __init__(self, extensions=None):
- super(Extensions, self).__init__()
-
- self.extensions = extensions or {}
+ #extend in subclass to specify the set of extensions
+ @property
+ def extensions(self):
+ return None
def get_extensions_info(self, context):
return {'extensions': {'values': self.extensions.values()}}
@@ -48,34 +49,15 @@ class Extensions(wsgi.Application):
class AdminExtensions(Extensions):
- def __init__(self, *args, **kwargs):
- super(AdminExtensions, self).__init__(*args, **kwargs)
-
- # TODO(dolph): Extensions should obviously provide this information
- # themselves, but hardcoding it here allows us to match
- # the API spec in the short term with minimal complexity.
- self.extensions['OS-KSADM'] = {
- 'name': 'Openstack Keystone Admin',
- 'namespace': 'http://docs.openstack.org/identity/api/ext/'
- 'OS-KSADM/v1.0',
- 'alias': 'OS-KSADM',
- 'updated': '2011-08-19T13:25:27-06:00',
- 'description': 'Openstack extensions to Keystone v2.0 API '
- 'enabling Admin Operations.',
- 'links': [
- {
- 'rel': 'describedby',
- # TODO(dolph): link needs to be revised after
- # bug 928059 merges
- 'type': 'text/html',
- 'href': 'https://github.com/openstack/identity-api',
- }
- ]
- }
+ @property
+ def extensions(self):
+ return extension.ADMIN_EXTENSIONS
class PublicExtensions(Extensions):
- pass
+ @property
+ def extensions(self):
+ return extension.PUBLIC_EXTENSIONS
def register_version(version):
diff --git a/keystone/exception.py b/keystone/exception.py
index db5f5005..5e1defba 100644
--- a/keystone/exception.py
+++ b/keystone/exception.py
@@ -13,10 +13,10 @@
# 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 re
from keystone.common import config
from keystone.common import logging
+from keystone.openstack.common.gettextutils import _ # noqa
CONF = config.CONF
@@ -29,15 +29,15 @@ _FATAL_EXCEPTION_FORMAT_ERRORS = False
class Error(StandardError):
"""Base error class.
- Child classes should define an HTTP status code, title, and a doc string.
+ Child classes should define an HTTP status code, title, and a
+ message_format.
"""
code = None
title = None
+ message_format = None
def __init__(self, message=None, **kwargs):
- """Use the doc string as the error message by default."""
-
try:
message = self._build_message(message, **kwargs)
except KeyError:
@@ -45,8 +45,8 @@ class Error(StandardError):
if _FATAL_EXCEPTION_FORMAT_ERRORS:
raise
else:
- LOG.warning('missing exception kwargs (programmer error)')
- message = self.__doc__
+ LOG.warning(_('missing exception kwargs (programmer error)'))
+ message = self.message_format
super(Error, self).__init__(message)
@@ -57,42 +57,31 @@ class Error(StandardError):
"""
if not message:
- message = re.sub('[ \n]+', ' ', self.__doc__ % kwargs)
- message = message.strip()
+ message = self.message_format % kwargs
return message
class ValidationError(Error):
- """Expecting to find %(attribute)s in %(target)s.
-
- The server could not comply with the request since it is either malformed
- or otherwise incorrect.
-
- The client is assumed to be in error.
-
- """
+ message_format = _("Expecting to find %(attribute)s in %(target)s."
+ " The server could not comply with the request"
+ " since it is either malformed or otherwise"
+ " incorrect. The client is assumed to be in error.")
code = 400
title = 'Bad Request'
class StringLengthExceeded(ValidationError):
- """String length exceeded.
-
- The length of string "%(string)s" exceeded the limit of column
- %(type)s(CHAR(%(length)d)).
-
- """
+ message_format = _("String length exceeded.The length of"
+ " string '%(string)s' exceeded the limit"
+ " of column %(type)s(CHAR(%(length)d)).")
class ValidationSizeError(Error):
- """Request attribute %(attribute)s must be less than or equal to %(size)i.
-
- The server could not comply with the request because the attribute
- size is invalid (too large).
-
- The client is assumed to be in error.
-
- """
+ message_format = _("Request attribute %(attribute)s must be"
+ " less than or equal to %(size)i. The server"
+ " could not comply with the request because"
+ " the attribute size is invalid (too large)."
+ " The client is assumed to be in error.")
code = 400
title = 'Bad Request'
@@ -103,19 +92,19 @@ class SecurityError(Error):
def _build_message(self, message, **kwargs):
"""Only returns detailed messages in debug mode."""
if CONF.debug:
- return message or self.__doc__ % kwargs
+ return message or self.message_format % kwargs
else:
- return self.__doc__ % kwargs
+ return self.message_format % kwargs
class Unauthorized(SecurityError):
- """The request you have made requires authentication."""
+ message_format = _("The request you have made requires authentication.")
code = 401
title = 'Unauthorized'
class AuthPluginException(Unauthorized):
- """Authentication plugin error."""
+ message_format = _("Authentication plugin error.")
def __init__(self, *args, **kwargs):
super(AuthPluginException, self).__init__(*args, **kwargs)
@@ -123,7 +112,7 @@ class AuthPluginException(Unauthorized):
class AuthMethodNotSupported(AuthPluginException):
- """Attempted to authenticate with an unsupported method."""
+ message_format = _("Attempted to authenticate with an unsupported method.")
def __init__(self, *args, **kwargs):
super(AuthMethodNotSupported, self).__init__(*args, **kwargs)
@@ -131,7 +120,7 @@ class AuthMethodNotSupported(AuthPluginException):
class AdditionalAuthRequired(AuthPluginException):
- """Additional authentications steps required."""
+ message_format = _("Additional authentications steps required.")
def __init__(self, auth_response=None, **kwargs):
super(AdditionalAuthRequired, self).__init__(message=None, **kwargs)
@@ -139,112 +128,111 @@ class AdditionalAuthRequired(AuthPluginException):
class Forbidden(SecurityError):
- """You are not authorized to perform the requested action."""
+ message_format = _("You are not authorized to perform the"
+ " requested action.")
code = 403
title = 'Forbidden'
class ForbiddenAction(Forbidden):
- """You are not authorized to perform the requested action, %(action)s."""
+ message_format = _("You are not authorized to perform the"
+ " requested action, %(action)s.")
class NotFound(Error):
- """Could not find, %(target)s."""
+ message_format = _("Could not find, %(target)s.")
code = 404
title = 'Not Found'
class EndpointNotFound(NotFound):
- """Could not find endpoint, %(endpoint_id)s."""
+ message_format = _("Could not find endpoint, %(endpoint_id)s.")
class MetadataNotFound(NotFound):
- """An unhandled exception has occurred: Could not find metadata."""
- # (dolph): metadata is not a user-facing concept,
- # so this exception should not be exposed
+ """(dolph): metadata is not a user-facing concept,
+ so this exception should not be exposed
+ """
+ message_format = _("An unhandled exception has occurred:"
+ " Could not find metadata.")
class PolicyNotFound(NotFound):
- """Could not find policy, %(policy_id)s."""
+ message_format = _("Could not find policy, %(policy_id)s.")
class RoleNotFound(NotFound):
- """Could not find role, %(role_id)s."""
+ message_format = _("Could not find role, %(role_id)s.")
class ServiceNotFound(NotFound):
- """Could not find service, %(service_id)s."""
+ message_format = _("Could not find service, %(service_id)s.")
class DomainNotFound(NotFound):
- """Could not find domain, %(domain_id)s."""
+ message_format = _("Could not find domain, %(domain_id)s.")
class ProjectNotFound(NotFound):
- """Could not find project, %(project_id)s."""
+ message_format = _("Could not find project, %(project_id)s.")
class TokenNotFound(NotFound):
- """Could not find token, %(token_id)s."""
+ message_format = _("Could not find token, %(token_id)s.")
class UserNotFound(NotFound):
- """Could not find user, %(user_id)s."""
+ message_format = _("Could not find user, %(user_id)s.")
class GroupNotFound(NotFound):
- """Could not find group, %(group_id)s."""
+ message_format = _("Could not find group, %(group_id)s.")
class TrustNotFound(NotFound):
- """Could not find trust, %(trust_id)s."""
+ message_format = _("Could not find trust, %(trust_id)s.")
class CredentialNotFound(NotFound):
- """Could not find credential, %(credential_id)s."""
+ message_format = _("Could not find credential, %(credential_id)s.")
class VersionNotFound(NotFound):
- """Could not find version, %(version)s."""
+ message_format = _("Could not find version, %(version)s.")
class Conflict(Error):
- """Conflict occurred attempting to store %(type)s.
-
- %(details)s
-
- """
+ message_format = _("Conflict occurred attempting to store %(type)s."
+ " %(details)s")
code = 409
title = 'Conflict'
class RequestTooLarge(Error):
- """Request is too large."""
+ message_format = _("Request is too large.")
code = 413
title = 'Request is too large.'
class UnexpectedError(Error):
- """An unexpected error prevented the server from fulfilling your request.
-
- %(exception)s
-
- """
+ message_format = _("An unexpected error prevented the server"
+ " from fulfilling your request. %(exception)s")
code = 500
title = 'Internal Server Error'
class MalformedEndpoint(UnexpectedError):
- """Malformed endpoint URL (%(endpoint)s), see ERROR log for details."""
+ message_format = _("Malformed endpoint URL (%(endpoint)s),"
+ " see ERROR log for details.")
class NotImplemented(Error):
- """The action you have requested has not been implemented."""
+ message_format = _("The action you have requested has not"
+ " been implemented.")
code = 501
title = 'Not Implemented'
class PasteConfigNotFound(UnexpectedError):
- """The Keystone paste configuration file %(config_file)s could not be
- found.
- """
+ message_format = _("The Keystone paste configuration file"
+ " %(config_file)s could not be found.")
diff --git a/keystone/identity/backends/kvs.py b/keystone/identity/backends/kvs.py
index 2eea08cf..0323d3d0 100644
--- a/keystone/identity/backends/kvs.py
+++ b/keystone/identity/backends/kvs.py
@@ -14,7 +14,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-from keystone import clean
from keystone.common import kvs
from keystone.common import utils
from keystone import exception
@@ -22,8 +21,14 @@ from keystone import identity
class Identity(kvs.Base, identity.Driver):
+ def __init__(self):
+ super(Identity, self).__init__()
+
+ def default_assignment_driver(self):
+ return "keystone.assignment.backends.kvs.Assignment"
+
# Public interface
- def authenticate_user(self, user_id=None, password=None):
+ def authenticate(self, user_id, password):
user_ref = None
try:
user_ref = self._get_user(user_id)
@@ -31,48 +36,7 @@ class Identity(kvs.Base, identity.Driver):
raise AssertionError('Invalid user / password')
if not utils.check_password(password, user_ref.get('password')):
raise AssertionError('Invalid user / password')
- return user_ref
-
- def authorize_for_project(self, user_ref, tenant_id=None):
- user_id = user_ref['id']
- tenant_ref = None
- metadata_ref = {}
- if tenant_id is not None:
- if tenant_id not in self.get_projects_for_user(user_id):
- raise AssertionError('Invalid tenant')
- try:
- tenant_ref = self.get_project(tenant_id)
- metadata_ref = self.get_metadata(user_id, tenant_id)
- except exception.ProjectNotFound:
- tenant_ref = None
- metadata_ref = {}
- except exception.MetadataNotFound:
- metadata_ref = {}
- return (identity.filter_user(user_ref), tenant_ref, metadata_ref)
-
- def get_project(self, tenant_id):
- try:
- return self.db.get('tenant-%s' % tenant_id)
- except exception.NotFound:
- raise exception.ProjectNotFound(project_id=tenant_id)
-
- def list_projects(self):
- tenant_keys = filter(lambda x: x.startswith("tenant-"),
- self.db.keys())
- return [self.db.get(key) for key in tenant_keys]
-
- def get_project_by_name(self, tenant_name, domain_id):
- try:
- return self.db.get('tenant_name-%s' % tenant_name)
- except exception.NotFound:
- raise exception.ProjectNotFound(project_id=tenant_name)
-
- def get_project_users(self, tenant_id):
- self.get_project(tenant_id)
- user_keys = filter(lambda x: x.startswith("user-"), self.db.keys())
- user_refs = [self.db.get(key) for key in user_keys]
- user_refs = filter(lambda x: tenant_id in x['tenants'], user_refs)
- return [identity.filter_user(user_ref) for user_ref in user_refs]
+ return identity.filter_user(user_ref)
def _get_user(self, user_id):
try:
@@ -93,93 +57,10 @@ class Identity(kvs.Base, identity.Driver):
return identity.filter_user(
self._get_user_by_name(user_name, domain_id))
- def get_metadata(self, user_id=None, tenant_id=None,
- domain_id=None, group_id=None):
- try:
- if user_id:
- if tenant_id:
- return self.db.get('metadata-%s-%s' % (tenant_id,
- user_id))
- else:
- return self.db.get('metadata-%s-%s' % (domain_id,
- user_id))
- else:
- if tenant_id:
- return self.db.get('metadata-%s-%s' % (tenant_id,
- group_id))
- else:
- return self.db.get('metadata-%s-%s' % (domain_id,
- group_id))
- except exception.NotFound:
- raise exception.MetadataNotFound()
-
- def get_role(self, role_id):
- try:
- return self.db.get('role-%s' % role_id)
- except exception.NotFound:
- raise exception.RoleNotFound(role_id=role_id)
-
def list_users(self):
user_ids = self.db.get('user_list', [])
return [self.get_user(x) for x in user_ids]
- def list_roles(self):
- role_ids = self.db.get('role_list', [])
- return [self.get_role(x) for x in role_ids]
-
- def get_projects_for_user(self, user_id):
- user_ref = self._get_user(user_id)
- return user_ref.get('tenants', [])
-
- def get_roles_for_user_and_project(self, user_id, tenant_id):
- self.get_user(user_id)
- self.get_project(tenant_id)
- try:
- metadata_ref = self.get_metadata(user_id, tenant_id)
- except exception.MetadataNotFound:
- metadata_ref = {}
- return metadata_ref.get('roles', [])
-
- def add_role_to_user_and_project(self, user_id, tenant_id, role_id):
- self.get_user(user_id)
- self.get_project(tenant_id)
- self.get_role(role_id)
- try:
- metadata_ref = self.get_metadata(user_id, tenant_id)
- except exception.MetadataNotFound:
- metadata_ref = {}
- roles = set(metadata_ref.get('roles', []))
- if role_id in roles:
- msg = ('User %s already has role %s in tenant %s'
- % (user_id, role_id, tenant_id))
- raise exception.Conflict(type='role grant', details=msg)
- roles.add(role_id)
- metadata_ref['roles'] = list(roles)
- self.update_metadata(user_id, tenant_id, metadata_ref)
-
- def remove_role_from_user_and_project(self, user_id, tenant_id, role_id):
- try:
- metadata_ref = self.get_metadata(user_id, tenant_id)
- except exception.MetadataNotFound:
- metadata_ref = {}
- roles = set(metadata_ref.get('roles', []))
- if role_id not in roles:
- msg = 'Cannot remove role that has not been granted, %s' % role_id
- raise exception.RoleNotFound(message=msg)
-
- roles.remove(role_id)
- metadata_ref['roles'] = list(roles)
-
- if not len(roles):
- self.db.delete('metadata-%s-%s' % (tenant_id, user_id))
- user_ref = self._get_user(user_id)
- tenants = set(user_ref.get('tenants', []))
- tenants.remove(tenant_id)
- user_ref['tenants'] = list(tenants)
- self.update_user(user_id, user_ref)
- else:
- self.update_metadata(user_id, tenant_id, metadata_ref)
-
# CRUD
def create_user(self, user_id, user):
try:
@@ -278,301 +159,6 @@ class Identity(kvs.Base, identity.Driver):
user_list.remove(user_id)
self.db.set('user_list', list(user_list))
- def create_project(self, tenant_id, tenant):
- tenant['name'] = clean.project_name(tenant['name'])
- try:
- self.get_project(tenant_id)
- except exception.ProjectNotFound:
- pass
- else:
- msg = 'Duplicate ID, %s.' % tenant_id
- raise exception.Conflict(type='tenant', details=msg)
-
- try:
- self.get_project_by_name(tenant['name'], tenant['domain_id'])
- except exception.ProjectNotFound:
- pass
- else:
- msg = 'Duplicate name, %s.' % tenant['name']
- raise exception.Conflict(type='tenant', details=msg)
-
- self.db.set('tenant-%s' % tenant_id, tenant)
- self.db.set('tenant_name-%s' % tenant['name'], tenant)
- return tenant
-
- def update_project(self, tenant_id, tenant):
- if 'name' in tenant:
- tenant['name'] = clean.project_name(tenant['name'])
- try:
- existing = self.db.get('tenant_name-%s' % tenant['name'])
- if existing and tenant_id != existing['id']:
- msg = 'Duplicate name, %s.' % tenant['name']
- raise exception.Conflict(type='tenant', details=msg)
- except exception.NotFound:
- pass
- # get the old name and delete it too
- try:
- old_project = self.db.get('tenant-%s' % tenant_id)
- except exception.NotFound:
- raise exception.ProjectNotFound(project_id=tenant_id)
- new_project = old_project.copy()
- new_project.update(tenant)
- new_project['id'] = tenant_id
- self.db.delete('tenant_name-%s' % old_project['name'])
- self.db.set('tenant-%s' % tenant_id, new_project)
- self.db.set('tenant_name-%s' % new_project['name'], new_project)
- return new_project
-
- def delete_project(self, tenant_id):
- try:
- old_project = self.db.get('tenant-%s' % tenant_id)
- except exception.NotFound:
- raise exception.ProjectNotFound(project_id=tenant_id)
- self.db.delete('tenant_name-%s' % old_project['name'])
- self.db.delete('tenant-%s' % tenant_id)
-
- def create_metadata(self, user_id, tenant_id, metadata,
- domain_id=None, group_id=None):
-
- return self.update_metadata(user_id, tenant_id, metadata,
- domain_id, group_id)
-
- def update_metadata(self, user_id, tenant_id, metadata,
- domain_id=None, group_id=None):
- if user_id:
- if tenant_id:
- self.db.set('metadata-%s-%s' % (tenant_id, user_id), metadata)
- user_ref = self._get_user(user_id)
- tenants = set(user_ref.get('tenants', []))
- if tenant_id not in tenants:
- tenants.add(tenant_id)
- user_ref['tenants'] = list(tenants)
- self.update_user(user_id, user_ref)
- else:
- self.db.set('metadata-%s-%s' % (domain_id, user_id), metadata)
- else:
- if tenant_id:
- self.db.set('metadata-%s-%s' % (tenant_id, group_id), metadata)
- else:
- self.db.set('metadata-%s-%s' % (domain_id, group_id), metadata)
- return metadata
-
- def create_role(self, role_id, role):
- try:
- self.get_role(role_id)
- except exception.RoleNotFound:
- pass
- else:
- msg = 'Duplicate ID, %s.' % role_id
- raise exception.Conflict(type='role', details=msg)
-
- for role_ref in self.list_roles():
- if role['name'] == role_ref['name']:
- msg = 'Duplicate name, %s.' % role['name']
- raise exception.Conflict(type='role', details=msg)
- self.db.set('role-%s' % role_id, role)
- role_list = set(self.db.get('role_list', []))
- role_list.add(role_id)
- self.db.set('role_list', list(role_list))
- return role
-
- def update_role(self, role_id, role):
- old_role_ref = None
- for role_ref in self.list_roles():
- if role['name'] == role_ref['name'] and role_id != role_ref['id']:
- msg = 'Duplicate name, %s.' % role['name']
- raise exception.Conflict(type='role', details=msg)
- if role_id == role_ref['id']:
- old_role_ref = role_ref
- if old_role_ref is None:
- raise exception.RoleNotFound(role_id=role_id)
- new_role = old_role_ref.copy()
- new_role.update(role)
- new_role['id'] = role_id
- self.db.set('role-%s' % role_id, new_role)
- return role
-
- def delete_role(self, role_id):
- self.get_role(role_id)
- metadata_keys = filter(lambda x: x.startswith("metadata-"),
- self.db.keys())
- for key in metadata_keys:
- meta_id1 = key.split('-')[1]
- meta_id2 = key.split('-')[2]
- try:
- self.delete_grant(role_id, project_id=meta_id1,
- user_id=meta_id2)
- except exception.NotFound:
- pass
- try:
- self.delete_grant(role_id, project_id=meta_id1,
- group_id=meta_id2)
- except exception.NotFound:
- pass
- try:
- self.delete_grant(role_id, domain_id=meta_id1,
- user_id=meta_id2)
- except exception.NotFound:
- pass
- try:
- self.delete_grant(role_id, domain_id=meta_id1,
- group_id=meta_id2)
- except exception.NotFound:
- pass
- self.db.delete('role-%s' % role_id)
- role_list = set(self.db.get('role_list', []))
- role_list.remove(role_id)
- self.db.set('role_list', list(role_list))
-
- def create_grant(self, role_id, user_id=None, group_id=None,
- domain_id=None, project_id=None):
-
- self.get_role(role_id)
- if user_id:
- self.get_user(user_id)
- if group_id:
- self.get_group(group_id)
- if domain_id:
- self.get_domain(domain_id)
- if project_id:
- self.get_project(project_id)
-
- try:
- metadata_ref = self.get_metadata(user_id, project_id,
- domain_id, group_id)
- except exception.MetadataNotFound:
- metadata_ref = {}
- roles = set(metadata_ref.get('roles', []))
- roles.add(role_id)
- metadata_ref['roles'] = list(roles)
- self.update_metadata(user_id, project_id, metadata_ref,
- domain_id, group_id)
-
- def list_grants(self, user_id=None, group_id=None,
- domain_id=None, project_id=None):
- if user_id:
- self.get_user(user_id)
- if group_id:
- self.get_group(group_id)
- if domain_id:
- self.get_domain(domain_id)
- if project_id:
- self.get_project(project_id)
-
- try:
- metadata_ref = self.get_metadata(user_id, project_id,
- domain_id, group_id)
- except exception.MetadataNotFound:
- metadata_ref = {}
- return [self.get_role(x) for x in metadata_ref.get('roles', [])]
-
- def get_grant(self, role_id, user_id=None, group_id=None,
- domain_id=None, project_id=None):
- self.get_role(role_id)
- if user_id:
- self.get_user(user_id)
- if group_id:
- self.get_group(group_id)
- if domain_id:
- self.get_domain(domain_id)
- if project_id:
- self.get_project(project_id)
-
- try:
- metadata_ref = self.get_metadata(user_id, project_id,
- domain_id, group_id)
- except exception.MetadataNotFound:
- metadata_ref = {}
- role_ids = set(metadata_ref.get('roles', []))
- if role_id not in role_ids:
- raise exception.RoleNotFound(role_id=role_id)
- return self.get_role(role_id)
-
- def delete_grant(self, role_id, user_id=None, group_id=None,
- domain_id=None, project_id=None):
- self.get_role(role_id)
- if user_id:
- self.get_user(user_id)
- if group_id:
- self.get_group(group_id)
- if domain_id:
- self.get_domain(domain_id)
- if project_id:
- self.get_project(project_id)
-
- try:
- metadata_ref = self.get_metadata(user_id, project_id,
- domain_id, group_id)
- except exception.MetadataNotFound:
- metadata_ref = {}
- roles = set(metadata_ref.get('roles', []))
- try:
- roles.remove(role_id)
- except KeyError:
- raise exception.RoleNotFound(role_id=role_id)
- metadata_ref['roles'] = list(roles)
- self.update_metadata(user_id, project_id, metadata_ref,
- domain_id, group_id)
-
- # domain crud
-
- def create_domain(self, domain_id, domain):
- try:
- self.get_domain(domain_id)
- except exception.DomainNotFound:
- pass
- else:
- msg = 'Duplicate ID, %s.' % domain_id
- raise exception.Conflict(type='domain', details=msg)
-
- try:
- self.get_domain_by_name(domain['name'])
- except exception.DomainNotFound:
- pass
- else:
- msg = 'Duplicate name, %s.' % domain['name']
- raise exception.Conflict(type='domain', details=msg)
-
- self.db.set('domain-%s' % domain_id, domain)
- self.db.set('domain_name-%s' % domain['name'], domain)
- domain_list = set(self.db.get('domain_list', []))
- domain_list.add(domain_id)
- self.db.set('domain_list', list(domain_list))
- return domain
-
- def list_domains(self):
- domain_ids = self.db.get('domain_list', [])
- return [self.get_domain(x) for x in domain_ids]
-
- def get_domain(self, domain_id):
- try:
- return self.db.get('domain-%s' % domain_id)
- except exception.NotFound:
- raise exception.DomainNotFound(domain_id=domain_id)
-
- def get_domain_by_name(self, domain_name):
- try:
- return self.db.get('domain_name-%s' % domain_name)
- except exception.NotFound:
- raise exception.DomainNotFound(domain_id=domain_name)
-
- def update_domain(self, domain_id, domain):
- orig_domain = self.get_domain(domain_id)
- domain['id'] = domain_id
- self.db.set('domain-%s' % domain_id, domain)
- self.db.set('domain_name-%s' % domain['name'], domain)
- if domain['name'] != orig_domain['name']:
- self.db.delete('domain_name-%s' % orig_domain['name'])
- return domain
-
- def delete_domain(self, domain_id):
- domain = self.get_domain(domain_id)
- self.db.delete('domain-%s' % domain_id)
- self.db.delete('domain_name-%s' % domain['name'])
- domain_list = set(self.db.get('domain_list', []))
- domain_list.remove(domain_id)
- self.db.set('domain_list', list(domain_list))
-
# group crud
def create_group(self, group_id, group):
diff --git a/keystone/identity/backends/ldap.py b/keystone/identity/backends/ldap.py
index dffbf835..91ea1e41 100644
--- a/keystone/identity/backends/ldap.py
+++ b/keystone/identity/backends/ldap.py
@@ -19,6 +19,7 @@ import uuid
import ldap
from keystone import clean
+from keystone.common import dependency
from keystone.common import ldap as common_ldap
from keystone.common import logging
from keystone.common import models
@@ -38,52 +39,22 @@ DEFAULT_DOMAIN = {
}
+@dependency.requires('assignment_api')
class Identity(identity.Driver):
def __init__(self):
super(Identity, self).__init__()
- self.LDAP_URL = CONF.ldap.url
- self.LDAP_USER = CONF.ldap.user
- self.LDAP_PASSWORD = CONF.ldap.password
- self.suffix = CONF.ldap.suffix
-
self.user = UserApi(CONF)
- self.project = ProjectApi(CONF)
- self.role = RoleApi(CONF)
self.group = GroupApi(CONF)
- def _validate_domain(self, ref):
- """Validate that either the default domain or nothing is specified.
-
- Also removes the domain from the ref so that LDAP doesn't have to
- persist the attribute.
-
- """
- ref = ref.copy()
- domain_id = ref.pop('domain_id', CONF.identity.default_domain_id)
- self._validate_domain_id(domain_id)
- return ref
-
- def _validate_domain_id(self, domain_id):
- """Validate that the domain ID specified belongs to the default domain.
-
- """
- if domain_id != CONF.identity.default_domain_id:
- raise exception.DomainNotFound(domain_id=domain_id)
-
- def _set_default_domain(self, ref):
- """Overrides any domain reference with the default domain."""
- if isinstance(ref, dict):
- ref = ref.copy()
- ref['domain_id'] = CONF.identity.default_domain_id
- return ref
- elif isinstance(ref, list):
- return [self._set_default_domain(x) for x in ref]
- else:
- raise ValueError(_('Expected dict or list: %s') % type(ref))
+ def default_assignment_driver(self):
+ return "keystone.assignment.backends.ldap.Assignment"
# Identity interface
- def authenticate_user(self, user_id=None, password=None):
+ def create_project(self, project_id, project):
+ return self.assignment_api.create_project(project_id, project)
+
+ def authenticate(self, user_id, password):
try:
user_ref = self._get_user(user_id)
except exception.UserNotFound:
@@ -97,133 +68,37 @@ class Identity(identity.Driver):
raise AssertionError('Invalid user / password')
except Exception:
raise AssertionError('Invalid user / password')
- return user_ref
-
- def authorize_for_project(self, user_ref, tenant_id=None):
- user_id = user_ref['id']
- tenant_ref = None
- metadata_ref = {}
-
- if tenant_id is not None:
- if tenant_id not in self.get_projects_for_user(user_id):
- raise AssertionError('Invalid tenant')
-
- try:
- tenant_ref = self.get_project(tenant_id)
- # TODO(termie): this should probably be made into a
- # get roles call
- metadata_ref = self.get_metadata(user_id, tenant_id)
- except exception.ProjectNotFound:
- tenant_ref = None
- metadata_ref = {}
- except exception.MetadataNotFound:
- metadata_ref = {}
-
- user_ref = self._set_default_domain(identity.filter_user(user_ref))
- return (user_ref, tenant_ref, metadata_ref)
-
- def get_project(self, tenant_id):
- return self._set_default_domain(self.project.get(tenant_id))
-
- def list_projects(self):
- return self._set_default_domain(self.project.get_all())
-
- def get_project_by_name(self, tenant_name, domain_id):
- self._validate_domain_id(domain_id)
- return self._set_default_domain(self.project.get_by_name(tenant_name))
+ return self.assignment_api._set_default_domain(
+ identity.filter_user(user_ref))
def _get_user(self, user_id):
return self.user.get(user_id)
def get_user(self, user_id):
ref = identity.filter_user(self._get_user(user_id))
- return self._set_default_domain(ref)
+ return self.assignment_api._set_default_domain(ref)
def list_users(self):
- return self._set_default_domain(self.user.get_all())
+ return (self.assignment_api._set_default_domain
+ (self.user.get_all_filtered()))
def get_user_by_name(self, user_name, domain_id):
- self._validate_domain_id(domain_id)
+ self.assignment_api._validate_default_domain_id(domain_id)
ref = identity.filter_user(self.user.get_by_name(user_name))
- return self._set_default_domain(ref)
-
- def get_metadata(self, user_id=None, tenant_id=None,
- domain_id=None, group_id=None):
- if domain_id is not None:
- raise NotImplemented('Domain metadata not supported by LDAP.')
- if not self.get_project(tenant_id) or not self.get_user(user_id):
- return {}
-
- metadata_ref = self.get_roles_for_user_and_project(user_id, tenant_id)
- if not metadata_ref:
- return {}
- return {'roles': metadata_ref}
-
- def get_role(self, role_id):
- return self.role.get(role_id)
-
- def list_roles(self):
- return self.role.get_all()
-
- def get_projects_for_user(self, user_id):
- self.get_user(user_id)
- user_dn = self.user._id_to_dn(user_id)
- associations = (self.role.list_project_roles_for_user
- (user_dn, self.project.tree_dn))
- return [p['id'] for p in
- self.project.get_user_projects(user_dn, associations)]
-
- def get_project_users(self, tenant_id):
- self.get_project(tenant_id)
- tenant_dn = self.project._id_to_dn(tenant_id)
- rolegrants = self.role.get_role_assignments(tenant_dn)
- users = [self.user.get_filtered(self.user._dn_to_id(user_id))
- for user_id in
- self.project.get_user_dns(tenant_id, rolegrants)]
- return self._set_default_domain(users)
-
- def get_roles_for_user_and_project(self, user_id, tenant_id):
- self.get_user(user_id)
- self.get_project(tenant_id)
- user_dn = self.user._id_to_dn(user_id)
- return [self.role._dn_to_id(a.role_dn)
- for a in self.role.get_role_assignments
- (self.project._id_to_dn(tenant_id))
- if a.user_dn == user_dn]
-
- def _subrole_id_to_dn(self, role_id, tenant_id):
- if tenant_id is None:
- return self.role._id_to_dn(role_id)
- else:
- return '%s=%s,%s' % (self.role.id_attr,
- ldap.dn.escape_dn_chars(role_id),
- self.project._id_to_dn(tenant_id))
-
- def add_role_to_user_and_project(self, user_id, tenant_id, role_id):
- self.get_user(user_id)
- self.get_project(tenant_id)
- self.get_role(role_id)
- user_dn = self.user._id_to_dn(user_id)
- role_dn = self._subrole_id_to_dn(role_id, tenant_id)
- self.role.add_user(role_id, role_dn, user_dn, user_id, tenant_id)
- tenant_dn = self.project._id_to_dn(tenant_id)
- return UserRoleAssociation(
- role_dn=role_dn,
- user_dn=user_dn,
- tenant_dn=tenant_dn)
+ return self.assignment_api._set_default_domain(ref)
# CRUD
def create_user(self, user_id, user):
- user = self._validate_domain(user)
+ user = self.assignment_api._validate_default_domain(user)
user_ref = self.user.create(user)
tenant_id = user.get('tenant_id')
- user_dn = self.user._id_to_dn(user['id'])
if tenant_id is not None:
- self.project.add_user(tenant_id, user_dn)
- return self._set_default_domain(identity.filter_user(user_ref))
+ self.assignment_api.add_user_to_project(tenant_id, user_id)
+ return (self.assignment_api._set_default_domain
+ (identity.filter_user(user_ref)))
def update_user(self, user_id, user):
- user = self._validate_domain(user)
+ user = self.assignment_api._validate_default_domain(user)
if 'id' in user and user['id'] != user_id:
raise exception.ValidationError('Cannot change user ID')
old_obj = self.user.get(user_id)
@@ -246,67 +121,12 @@ class Identity(identity.Driver):
user['enabled_nomask'] = old_obj['enabled_nomask']
self.user.mask_enabled_attribute(user)
self.user.update(user_id, user, old_obj)
- return self._set_default_domain(self.user.get_filtered(user_id))
-
- def create_project(self, tenant_id, tenant):
- tenant = self._validate_domain(tenant)
- tenant['name'] = clean.project_name(tenant['name'])
- data = tenant.copy()
- if 'id' not in data or data['id'] is None:
- data['id'] = str(uuid.uuid4().hex)
- if 'description' in data and data['description'] in ['', None]:
- data.pop('description')
- return self._set_default_domain(self.project.create(data))
-
- def update_project(self, tenant_id, tenant):
- tenant = self._validate_domain(tenant)
- if 'name' in tenant:
- tenant['name'] = clean.project_name(tenant['name'])
- return self._set_default_domain(self.project.update(tenant_id, tenant))
-
- def create_metadata(self, user_id, tenant_id, metadata):
- return {}
-
- def create_role(self, role_id, role):
- try:
- self.get_role(role_id)
- except exception.NotFound:
- pass
- else:
- msg = 'Duplicate ID, %s.' % role_id
- raise exception.Conflict(type='role', details=msg)
-
- try:
- self.role.get_by_name(role['name'])
- except exception.NotFound:
- pass
- else:
- msg = 'Duplicate name, %s.' % role['name']
- raise exception.Conflict(type='role', details=msg)
-
- return self.role.create(role)
-
- def delete_role(self, role_id):
- return self.role.delete(role_id, self.project.tree_dn)
-
- def delete_project(self, tenant_id):
- if self.project.subtree_delete_enabled:
- self.project.deleteTree(id)
- else:
- tenant_dn = self.project._id_to_dn(tenant_id)
- self.role.roles_delete_subtree_by_project(tenant_dn)
- self.project.delete(tenant_id)
+ return (self.assignment_api._set_default_domain
+ (self.user.get_filtered(user_id)))
def delete_user(self, user_id):
+ self.assignment_api.delete_user(user_id)
user_dn = self.user._id_to_dn(user_id)
- for ref in self.role.list_global_roles_for_user(user_dn):
- self.role.delete_user(ref.role_dn, ref.user_dn, ref.project_dn,
- user_id, self.role._dn_to_id(ref.role_dn))
- for ref in self.role.list_project_roles_for_user(user_dn,
- self.project.tree_dn):
- self.role.delete_user(ref.role_dn, ref.user_dn, ref.project_dn,
- user_id, self.role._dn_to_id(ref.role_dn))
-
groups = self.group.list_user_groups(user_dn)
for group in groups:
self.group.remove_user(user_dn, group['id'], user_id)
@@ -317,30 +137,22 @@ class Identity(identity.Driver):
self.user._id_to_dn(user_id))
self.user.delete(user_id)
- def remove_role_from_user_and_project(self, user_id, tenant_id, role_id):
- role_dn = self._subrole_id_to_dn(role_id, tenant_id)
- return self.role.delete_user(role_dn,
- self.user._id_to_dn(user_id),
- self.project._id_to_dn(tenant_id),
- user_id, role_id)
-
- def update_role(self, role_id, role):
- self.get_role(role_id)
- self.role.update(role_id, role)
-
def create_group(self, group_id, group):
- group = self._validate_domain(group)
+ group = self.assignment_api._validate_default_domain(group)
group['name'] = clean.group_name(group['name'])
- return self._set_default_domain(self.group.create(group))
+ return self.assignment_api._set_default_domain(
+ self.group.create(group))
def get_group(self, group_id):
- return self._set_default_domain(self.group.get(group_id))
+ return self.assignment_api._set_default_domain(
+ self.group.get(group_id))
def update_group(self, group_id, group):
- group = self._validate_domain(group)
+ group = self.assignment_api._validate_default_domain(group)
if 'name' in group:
group['name'] = clean.group_name(group['name'])
- return self._set_default_domain(self.group.update(group_id, group))
+ return (self.assignment_api._set_default_domain
+ (self.group.update(group_id, group)))
def delete_group(self, group_id):
return self.group.delete(group_id)
@@ -360,10 +172,11 @@ class Identity(identity.Driver):
def list_groups_for_user(self, user_id):
self.get_user(user_id)
user_dn = self.user._id_to_dn(user_id)
- return self._set_default_domain(self.group.list_user_groups(user_dn))
+ return (self.assignment_api._set_default_domain
+ (self.group.list_user_groups(user_dn)))
def list_groups(self):
- return self._set_default_domain(self.group.get_all())
+ return self.assignment_api._set_default_domain(self.group.get_all())
def list_users_in_group(self, group_id):
self.get_group(group_id)
@@ -371,13 +184,13 @@ class Identity(identity.Driver):
for user_dn in self.group.list_group_users(group_id):
user_id = self.user._dn_to_id(user_dn)
try:
- users.append(self.user.get(user_id))
+ users.append(self.user.get_filtered(user_id))
except exception.UserNotFound:
LOG.debug(_("Group member '%(user_dn)s' not found in"
" '%(group_id)s'. The user should be removed"
" from the group. The user will be ignored.") %
dict(user_dn=user_dn, group_id=group_id))
- return self._set_default_domain(users)
+ return self.assignment_api._set_default_domain(users)
def check_user_in_group(self, user_id, group_id):
self.get_user(user_id)
@@ -390,27 +203,6 @@ class Identity(identity.Driver):
break
return found
- def create_domain(self, domain_id, domain):
- if domain_id == CONF.identity.default_domain_id:
- msg = 'Duplicate ID, %s.' % domain_id
- raise exception.Conflict(type='domain', details=msg)
- raise exception.Forbidden('Domains are read-only against LDAP')
-
- def get_domain(self, domain_id):
- self._validate_domain_id(domain_id)
- return DEFAULT_DOMAIN
-
- def update_domain(self, domain_id, domain):
- self._validate_domain_id(domain_id)
- raise exception.Forbidden('Domains are read-only against LDAP')
-
- def delete_domain(self, domain_id):
- self._validate_domain_id(domain_id)
- raise exception.Forbidden('Domains are read-only against LDAP')
-
- def list_domains(self):
- return [DEFAULT_DOMAIN]
-
# TODO(termie): turn this into a data object and move logic to driver
class UserApi(common_ldap.EnabledEmuMixIn, common_ldap.BaseLdap):
@@ -475,292 +267,8 @@ class UserApi(common_ldap.EnabledEmuMixIn, common_ldap.BaseLdap):
user = self.get(user_id)
return identity.filter_user(user)
-
-# TODO(termie): turn this into a data object and move logic to driver
-class ProjectApi(common_ldap.EnabledEmuMixIn, common_ldap.BaseLdap):
- DEFAULT_OU = 'ou=Projects'
- DEFAULT_STRUCTURAL_CLASSES = []
- DEFAULT_OBJECTCLASS = 'groupOfNames'
- DEFAULT_ID_ATTR = 'cn'
- DEFAULT_MEMBER_ATTRIBUTE = 'member'
- DEFAULT_ATTRIBUTE_IGNORE = []
- NotFound = exception.ProjectNotFound
- notfound_arg = 'project_id' # NOTE(yorik-sar): while options_name = tenant
- options_name = 'tenant'
- attribute_mapping = {'name': 'ou',
- 'description': 'description',
- 'tenantId': 'cn',
- 'enabled': 'enabled',
- 'domain_id': 'domain_id'}
- model = models.Project
-
- def __init__(self, conf):
- super(ProjectApi, self).__init__(conf)
- self.attribute_mapping['name'] = conf.ldap.tenant_name_attribute
- self.attribute_mapping['description'] = conf.ldap.tenant_desc_attribute
- self.attribute_mapping['enabled'] = conf.ldap.tenant_enabled_attribute
- self.attribute_mapping['domain_id'] = (
- conf.ldap.tenant_domain_id_attribute)
- self.member_attribute = (getattr(conf.ldap, 'tenant_member_attribute')
- or self.DEFAULT_MEMBER_ATTRIBUTE)
- self.attribute_ignore = (getattr(conf.ldap, 'tenant_attribute_ignore')
- or self.DEFAULT_ATTRIBUTE_IGNORE)
-
- def create(self, values):
- self.affirm_unique(values)
- data = values.copy()
- if data.get('id') is None:
- data['id'] = uuid.uuid4().hex
- return super(ProjectApi, self).create(data)
-
- def get_user_projects(self, user_dn, associations):
- """Returns list of tenants a user has access to
- """
-
- project_ids = set()
- for assoc in associations:
- project_ids.add(self._dn_to_id(assoc.project_dn))
- projects = []
- for project_id in project_ids:
- #slower to get them one at a time, but a huge list could blow out
- #the connection. This is the safer way
- projects.append(self.get(project_id))
- return projects
-
- def add_user(self, tenant_id, user_dn):
- conn = self.get_connection()
- try:
- conn.modify_s(
- self._id_to_dn(tenant_id),
- [(ldap.MOD_ADD,
- self.member_attribute,
- user_dn)])
- except ldap.TYPE_OR_VALUE_EXISTS:
- # As adding a user to a tenant is done implicitly in several
- # places, and is not part of the exposed API, it's easier for us to
- # just ignore this instead of raising exception.Conflict.
- pass
-
- def remove_user(self, tenant_id, user_dn, user_id):
- conn = self.get_connection()
- try:
- conn.modify_s(self._id_to_dn(tenant_id),
- [(ldap.MOD_DELETE,
- self.member_attribute,
- user_dn)])
- except ldap.NO_SUCH_ATTRIBUTE:
- raise exception.NotFound(user_id)
-
- def get_user_dns(self, tenant_id, rolegrants, role_dn=None):
- tenant = self._ldap_get(tenant_id)
- res = set()
- if not role_dn:
- # Get users who have default tenant mapping
- for user_dn in tenant[1].get(self.member_attribute, []):
- if self.use_dumb_member and user_dn == self.dumb_member:
- continue
- res.add(user_dn)
-
- # Get users who are explicitly mapped via a tenant
- for rolegrant in rolegrants:
- if role_dn is None or rolegrant.role_dn == role_dn:
- res.add(rolegrant.user_dn)
- return list(res)
-
- def update(self, id, values):
- old_obj = self.get(id)
- if old_obj['name'] != values['name']:
- msg = 'Changing Name not supported by LDAP'
- raise exception.NotImplemented(message=msg)
- return super(ProjectApi, self).update(id, values, old_obj)
-
-
-class UserRoleAssociation(object):
- """Role Grant model."""
-
- def __init__(self, user_dn=None, role_dn=None, tenant_dn=None,
- *args, **kw):
- self.user_dn = user_dn
- self.role_dn = role_dn
- self.project_dn = tenant_dn
-
-
-class GroupRoleAssociation(object):
- """Role Grant model."""
-
- def __init__(self, group_dn=None, role_dn=None, tenant_dn=None,
- *args, **kw):
- self.group_dn = group_dn
- self.role_dn = role_dn
- self.project_dn = tenant_dn
-
-
-# TODO(termie): turn this into a data object and move logic to driver
-class RoleApi(common_ldap.BaseLdap):
- DEFAULT_OU = 'ou=Roles'
- DEFAULT_STRUCTURAL_CLASSES = []
- DEFAULT_OBJECTCLASS = 'organizationalRole'
- DEFAULT_MEMBER_ATTRIBUTE = 'roleOccupant'
- DEFAULT_ATTRIBUTE_IGNORE = []
- NotFound = exception.RoleNotFound
- options_name = 'role'
- attribute_mapping = {'name': 'ou',
- #'serviceId': 'service_id',
- }
- model = models.Role
-
- def __init__(self, conf):
- super(RoleApi, self).__init__(conf)
- self.attribute_mapping['name'] = conf.ldap.role_name_attribute
- self.member_attribute = (getattr(conf.ldap, 'role_member_attribute')
- or self.DEFAULT_MEMBER_ATTRIBUTE)
- self.attribute_ignore = (getattr(conf.ldap, 'role_attribute_ignore')
- or self.DEFAULT_ATTRIBUTE_IGNORE)
-
- def get(self, id, filter=None):
- model = super(RoleApi, self).get(id, filter)
- return model
-
- def create(self, values):
- return super(RoleApi, self).create(values)
-
- def add_user(self, role_id, role_dn, user_dn, user_id, tenant_id=None):
- conn = self.get_connection()
- try:
- conn.modify_s(role_dn, [(ldap.MOD_ADD,
- self.member_attribute, user_dn)])
- except ldap.TYPE_OR_VALUE_EXISTS:
- msg = ('User %s already has role %s in tenant %s'
- % (user_id, role_id, tenant_id))
- raise exception.Conflict(type='role grant', details=msg)
- except ldap.NO_SUCH_OBJECT:
- if tenant_id is None or self.get(role_id) is None:
- raise Exception(_("Role %s not found") % (role_id,))
-
- attrs = [('objectClass', [self.object_class]),
- (self.member_attribute, [user_dn])]
-
- if self.use_dumb_member:
- attrs[1][1].append(self.dumb_member)
- try:
- conn.add_s(role_dn, attrs)
- except Exception as inst:
- raise inst
-
- def delete_user(self, role_dn, user_dn, tenant_dn,
- user_id, role_id):
- conn = self.get_connection()
- try:
- conn.modify_s(role_dn, [(ldap.MOD_DELETE,
- self.member_attribute, user_dn)])
- except ldap.NO_SUCH_OBJECT:
- if tenant_dn is None:
- raise exception.RoleNotFound(role_id=role_id)
- attrs = [('objectClass', [self.object_class]),
- (self.member_attribute, [user_dn])]
-
- if self.use_dumb_member:
- attrs[1][1].append(self.dumb_member)
- try:
- conn.add_s(role_dn, attrs)
- except Exception as inst:
- raise inst
- except ldap.NO_SUCH_ATTRIBUTE:
- raise exception.UserNotFound(user_id=user_id)
-
- def get_role_assignments(self, tenant_dn):
- conn = self.get_connection()
- query = '(objectClass=%s)' % self.object_class
-
- try:
- roles = conn.search_s(tenant_dn, ldap.SCOPE_ONELEVEL, query)
- except ldap.NO_SUCH_OBJECT:
- return []
-
- res = []
- for role_dn, attrs in roles:
- try:
- user_dns = attrs[self.member_attribute]
- except KeyError:
- continue
- for user_dn in user_dns:
- if self.use_dumb_member and user_dn == self.dumb_member:
- continue
- res.append(UserRoleAssociation(
- user_dn=user_dn,
- role_dn=role_dn,
- tenant_dn=tenant_dn))
-
- return res
-
- def list_global_roles_for_user(self, user_dn):
- roles = self.get_all('(%s=%s)' % (self.member_attribute, user_dn))
- return [UserRoleAssociation(
- role_dn=role.dn,
- user_dn=user_dn) for role in roles]
-
- def list_project_roles_for_user(self, user_dn, project_subtree):
- conn = self.get_connection()
- query = '(&(objectClass=%s)(%s=%s))' % (self.object_class,
- self.member_attribute,
- user_dn)
- try:
- roles = conn.search_s(project_subtree,
- ldap.SCOPE_SUBTREE,
- query)
- except ldap.NO_SUCH_OBJECT:
- return []
-
- res = []
- for role_dn, _ in roles:
- #ldap.dn.dn2str returns an array, where the first
- #element is the first segment.
- #For a role assignment, this contains the role ID,
- #The remainder is the DN of the tenant.
- tenant = ldap.dn.str2dn(role_dn)
- tenant.pop(0)
- tenant_dn = ldap.dn.dn2str(tenant)
- res.append(UserRoleAssociation(
- user_dn=user_dn,
- role_dn=role_dn,
- tenant_dn=tenant_dn))
- return res
-
- def roles_delete_subtree_by_project(self, tenant_dn):
- conn = self.get_connection()
- query = '(objectClass=%s)' % self.object_class
- try:
- roles = conn.search_s(tenant_dn, ldap.SCOPE_ONELEVEL, query)
- for role_dn, _ in roles:
- try:
- conn.delete_s(role_dn)
- except Exception as inst:
- raise inst
- except ldap.NO_SUCH_OBJECT:
- pass
-
- def update(self, role_id, role):
- if role['id'] != role_id:
- raise exception.ValidationError('Cannot change role ID')
- try:
- old_name = self.get_by_name(role['name'])
- raise exception.Conflict('Cannot duplicate name %s' % old_name)
- except exception.NotFound:
- pass
- return super(RoleApi, self).update(role_id, role)
-
- def delete(self, id, tenant_dn):
- conn = self.get_connection()
- query = '(&(objectClass=%s)(%s=%s))' % (self.object_class,
- self.id_attr, id)
- try:
- for role_dn, _ in conn.search_s(tenant_dn,
- ldap.SCOPE_SUBTREE,
- query):
- conn.delete_s(role_dn)
- except ldap.NO_SUCH_OBJECT:
- pass
- super(RoleApi, self).delete(id)
+ def get_all_filtered(self):
+ return [identity.filter_user(user) for user in self.get_all()]
class GroupApi(common_ldap.BaseLdap):
diff --git a/keystone/identity/backends/pam.py b/keystone/identity/backends/pam.py
index 9c4bbf38..2a6ee621 100644
--- a/keystone/identity/backends/pam.py
+++ b/keystone/identity/backends/pam.py
@@ -58,21 +58,13 @@ class PamIdentity(identity.Driver):
Tenant is always the same as User, root user has admin role.
"""
- def authenticate_user(self, user_id=None, password=None):
+ def authenticate(self, user_id, password):
auth = pam.authenticate if pam else PAM_authenticate
if not auth(user_id, password):
raise AssertionError('Invalid user / password')
user = {'id': user_id, 'name': user_id}
return user
- def authorize_for_project(self, user_ref, tenant_id=None):
- user_id = user_ref['id']
- metadata = {}
- if user_id == 'root':
- metadata['is_admin'] = True
- tenant = {'id': user_id, 'name': user_id}
- return (user_ref, tenant, metadata)
-
def get_project(self, tenant_id):
return {'id': tenant_id, 'name': tenant_id}
@@ -134,16 +126,16 @@ class PamIdentity(identity.Driver):
def delete_project(self, tenant_id, tenant):
raise NotImplementedError()
- def get_metadata(self, user_id, tenant_id):
+ def _get_metadata(self, user_id, tenant_id):
metadata = {}
if user_id == 'root':
metadata['is_admin'] = True
return metadata
- def create_metadata(self, user_id, tenant_id, metadata):
+ def _create_metadata(self, user_id, tenant_id, metadata):
raise NotImplementedError()
- def update_metadata(self, user_id, tenant_id, metadata):
+ def _update_metadata(self, user_id, tenant_id, metadata):
raise NotImplementedError()
def create_role(self, role_id, role):
diff --git a/keystone/identity/backends/sql.py b/keystone/identity/backends/sql.py
index f81feb1d..bff41106 100644
--- a/keystone/identity/backends/sql.py
+++ b/keystone/identity/backends/sql.py
@@ -14,7 +14,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-from keystone import clean
+from keystone.common import dependency
from keystone.common import sql
from keystone.common.sql import migration
from keystone.common import utils
@@ -51,78 +51,6 @@ class Group(sql.ModelBase, sql.DictBase):
__table_args__ = (sql.UniqueConstraint('domain_id', 'name'), {})
-class Domain(sql.ModelBase, sql.DictBase):
- __tablename__ = 'domain'
- attributes = ['id', 'name', 'enabled']
- id = sql.Column(sql.String(64), primary_key=True)
- name = sql.Column(sql.String(64), unique=True, nullable=False)
- enabled = sql.Column(sql.Boolean, default=True)
- extra = sql.Column(sql.JsonBlob())
-
-
-class Project(sql.ModelBase, sql.DictBase):
- __tablename__ = 'project'
- attributes = ['id', 'name', 'domain_id', 'description', 'enabled']
- id = sql.Column(sql.String(64), primary_key=True)
- name = sql.Column(sql.String(64), nullable=False)
- domain_id = sql.Column(sql.String(64), sql.ForeignKey('domain.id'),
- nullable=False)
- description = sql.Column(sql.Text())
- enabled = sql.Column(sql.Boolean)
- extra = sql.Column(sql.JsonBlob())
- # Unique constraint across two columns to create the separation
- # rather than just only 'name' being unique
- __table_args__ = (sql.UniqueConstraint('domain_id', 'name'), {})
-
-
-class Role(sql.ModelBase, sql.DictBase):
- __tablename__ = 'role'
- attributes = ['id', 'name']
- id = sql.Column(sql.String(64), primary_key=True)
- name = sql.Column(sql.String(64), unique=True, nullable=False)
- extra = sql.Column(sql.JsonBlob())
-
-
-class BaseGrant(sql.DictBase):
- def to_dict(self):
- """Override parent to_dict() method with a simpler implementation.
-
- Grant tables don't have non-indexed 'extra' attributes, so the
- parent implementation is not applicable.
- """
- return dict(self.iteritems())
-
-
-class UserProjectGrant(sql.ModelBase, BaseGrant):
- __tablename__ = 'user_project_metadata'
- user_id = sql.Column(sql.String(64),
- primary_key=True)
- project_id = sql.Column(sql.String(64),
- primary_key=True)
- data = sql.Column(sql.JsonBlob())
-
-
-class UserDomainGrant(sql.ModelBase, BaseGrant):
- __tablename__ = 'user_domain_metadata'
- user_id = sql.Column(sql.String(64), primary_key=True)
- domain_id = sql.Column(sql.String(64), primary_key=True)
- data = sql.Column(sql.JsonBlob())
-
-
-class GroupProjectGrant(sql.ModelBase, BaseGrant):
- __tablename__ = 'group_project_metadata'
- group_id = sql.Column(sql.String(64), primary_key=True)
- project_id = sql.Column(sql.String(64), primary_key=True)
- data = sql.Column(sql.JsonBlob())
-
-
-class GroupDomainGrant(sql.ModelBase, BaseGrant):
- __tablename__ = 'group_domain_metadata'
- group_id = sql.Column(sql.String(64), primary_key=True)
- domain_id = sql.Column(sql.String(64), primary_key=True)
- data = sql.Column(sql.JsonBlob())
-
-
class UserGroupMembership(sql.ModelBase, sql.DictBase):
"""Group membership join table."""
__tablename__ = 'user_group_membership'
@@ -134,7 +62,11 @@ class UserGroupMembership(sql.ModelBase, sql.DictBase):
primary_key=True)
+@dependency.requires('assignment_api')
class Identity(sql.Base, identity.Driver):
+ def default_assignment_driver(self):
+ return "keystone.assignment.backends.sql.Assignment"
+
# Internal interface to manage the database
def db_sync(self, version=None):
migration.db_sync(version=version)
@@ -154,7 +86,7 @@ class Identity(sql.Base, identity.Driver):
return utils.check_password(password, user_ref.password)
# Identity interface
- def authenticate_user(self, user_id=None, password=None):
+ def authenticate(self, user_id, password):
session = self.get_session()
user_ref = None
try:
@@ -163,464 +95,7 @@ class Identity(sql.Base, identity.Driver):
raise AssertionError('Invalid user / password')
if not self._check_password(password, user_ref):
raise AssertionError('Invalid user / password')
- return user_ref
-
- def authorize_for_project(self, user_ref, tenant_id=None):
- user_id = user_ref['id']
- tenant_ref = None
- metadata_ref = {}
- if tenant_id is not None:
- # FIXME(gyee): this should really be
- # get_roles_for_user_and_project() after the dusts settle
- if tenant_id not in self.get_projects_for_user(user_id):
- raise AssertionError('Invalid project')
- try:
- tenant_ref = self.get_project(tenant_id)
- metadata_ref = self.get_metadata(user_id, tenant_id)
- except exception.ProjectNotFound:
- tenant_ref = None
- metadata_ref = {}
- except exception.MetadataNotFound:
- metadata_ref = {}
- user_ref = identity.filter_user(user_ref.to_dict())
- return (user_ref, tenant_ref, metadata_ref)
-
- def _get_project(self, session, project_id):
- project_ref = session.query(Project).get(project_id)
- if project_ref is None:
- raise exception.ProjectNotFound(project_id=project_id)
- return project_ref
-
- def get_project(self, tenant_id):
- session = self.get_session()
- return self._get_project(session, tenant_id).to_dict()
-
- def get_project_by_name(self, tenant_name, domain_id):
- session = self.get_session()
- query = session.query(Project)
- query = query.filter_by(name=tenant_name)
- query = query.filter_by(domain_id=domain_id)
- try:
- project_ref = query.one()
- except sql.NotFound:
- raise exception.ProjectNotFound(project_id=tenant_name)
- return project_ref.to_dict()
-
- def get_project_user_ids(self, tenant_id):
- session = self.get_session()
- self.get_project(tenant_id)
- query = session.query(UserProjectGrant)
- query = query.filter(UserProjectGrant.project_id == tenant_id)
- project_refs = query.all()
- return [project_ref.user_id for project_ref in project_refs]
-
- def get_project_users(self, tenant_id):
- session = self.get_session()
- self.get_project(tenant_id)
- user_refs = []
- for user_id in self.get_project_user_ids(tenant_id):
- query = session.query(User)
- query = query.filter(User.id == user_id)
- user_ref = query.first()
- user_refs.append(identity.filter_user(user_ref.to_dict()))
- return user_refs
-
- def get_metadata(self, user_id=None, tenant_id=None,
- domain_id=None, group_id=None):
- session = self.get_session()
-
- if user_id:
- if tenant_id:
- q = session.query(UserProjectGrant)
- q = q.filter_by(project_id=tenant_id)
- elif domain_id:
- q = session.query(UserDomainGrant)
- q = q.filter_by(domain_id=domain_id)
- q = q.filter_by(user_id=user_id)
- elif group_id:
- if tenant_id:
- q = session.query(GroupProjectGrant)
- q = q.filter_by(project_id=tenant_id)
- elif domain_id:
- q = session.query(GroupDomainGrant)
- q = q.filter_by(domain_id=domain_id)
- q = q.filter_by(group_id=group_id)
- try:
- return q.one().data
- except sql.NotFound:
- raise exception.MetadataNotFound()
-
- def create_grant(self, role_id, user_id=None, group_id=None,
- domain_id=None, project_id=None):
- session = self.get_session()
- self._get_role(session, role_id)
- if user_id:
- self._get_user(session, user_id)
- if group_id:
- self._get_group(session, group_id)
- if domain_id:
- self._get_domain(session, domain_id)
- if project_id:
- self._get_project(session, project_id)
-
- try:
- metadata_ref = self.get_metadata(user_id, project_id,
- domain_id, group_id)
- is_new = False
- except exception.MetadataNotFound:
- metadata_ref = {}
- is_new = True
- roles = set(metadata_ref.get('roles', []))
- roles.add(role_id)
- metadata_ref['roles'] = list(roles)
- if is_new:
- self.create_metadata(user_id, project_id, metadata_ref,
- domain_id, group_id)
- else:
- self.update_metadata(user_id, project_id, metadata_ref,
- domain_id, group_id)
-
- def list_grants(self, user_id=None, group_id=None,
- domain_id=None, project_id=None):
- session = self.get_session()
- if user_id:
- self._get_user(session, user_id)
- if group_id:
- self._get_group(session, group_id)
- if domain_id:
- self._get_domain(session, domain_id)
- if project_id:
- self._get_project(session, project_id)
-
- try:
- metadata_ref = self.get_metadata(user_id, project_id,
- domain_id, group_id)
- except exception.MetadataNotFound:
- metadata_ref = {}
- return [self.get_role(x) for x in metadata_ref.get('roles', [])]
-
- def get_grant(self, role_id, user_id=None, group_id=None,
- domain_id=None, project_id=None):
- session = self.get_session()
- role_ref = self._get_role(session, role_id)
- if user_id:
- self._get_user(session, user_id)
- if group_id:
- self._get_group(session, group_id)
- if domain_id:
- self._get_domain(session, domain_id)
- if project_id:
- self._get_project(session, project_id)
-
- try:
- metadata_ref = self.get_metadata(user_id, project_id,
- domain_id, group_id)
- except exception.MetadataNotFound:
- metadata_ref = {}
- role_ids = set(metadata_ref.get('roles', []))
- if role_id not in role_ids:
- raise exception.RoleNotFound(role_id=role_id)
- return role_ref.to_dict()
-
- def delete_grant(self, role_id, user_id=None, group_id=None,
- domain_id=None, project_id=None):
- session = self.get_session()
- self._get_role(session, role_id)
- if user_id:
- self._get_user(session, user_id)
- if group_id:
- self._get_group(session, group_id)
- if domain_id:
- self._get_domain(session, domain_id)
- if project_id:
- self._get_project(session, project_id)
-
- try:
- metadata_ref = self.get_metadata(user_id, project_id,
- domain_id, group_id)
- is_new = False
- except exception.MetadataNotFound:
- metadata_ref = {}
- is_new = True
- roles = set(metadata_ref.get('roles', []))
- try:
- roles.remove(role_id)
- except KeyError:
- raise exception.RoleNotFound(role_id=role_id)
- metadata_ref['roles'] = list(roles)
- if is_new:
- self.create_metadata(user_id, project_id, metadata_ref,
- domain_id, group_id)
- else:
- self.update_metadata(user_id, project_id, metadata_ref,
- domain_id, group_id)
-
- def list_projects(self):
- session = self.get_session()
- tenant_refs = session.query(Project).all()
- return [tenant_ref.to_dict() for tenant_ref in tenant_refs]
-
- def get_projects_for_user(self, user_id):
- session = self.get_session()
- self._get_user(session, user_id)
- query = session.query(UserProjectGrant)
- query = query.filter_by(user_id=user_id)
- membership_refs = query.all()
- return [x.project_id for x in membership_refs]
-
- def _get_user_group_project_roles(self, metadata_ref, user_id, project_id):
- group_refs = self.list_groups_for_user(user_id=user_id)
- for x in group_refs:
- try:
- metadata_ref.update(
- self.get_metadata(group_id=x['id'],
- tenant_id=project_id))
- except exception.MetadataNotFound:
- # no group grant, skip
- pass
-
- def _get_user_project_roles(self, metadata_ref, user_id, project_id):
- try:
- metadata_ref.update(self.get_metadata(user_id, project_id))
- except exception.MetadataNotFound:
- pass
-
- def get_roles_for_user_and_project(self, user_id, tenant_id):
- session = self.get_session()
- self._get_user(session, user_id)
- self._get_project(session, tenant_id)
- metadata_ref = {}
- self._get_user_project_roles(metadata_ref, user_id, tenant_id)
- self._get_user_group_project_roles(metadata_ref, user_id, tenant_id)
- return list(set(metadata_ref.get('roles', [])))
-
- def add_role_to_user_and_project(self, user_id, tenant_id, role_id):
- session = self.get_session()
- self._get_user(session, user_id)
- self._get_project(session, tenant_id)
- self._get_role(session, role_id)
- try:
- metadata_ref = self.get_metadata(user_id, tenant_id)
- is_new = False
- except exception.MetadataNotFound:
- metadata_ref = {}
- is_new = True
- roles = set(metadata_ref.get('roles', []))
- if role_id in roles:
- msg = ('User %s already has role %s in tenant %s'
- % (user_id, role_id, tenant_id))
- raise exception.Conflict(type='role grant', details=msg)
- roles.add(role_id)
- metadata_ref['roles'] = list(roles)
- if is_new:
- self.create_metadata(user_id, tenant_id, metadata_ref)
- else:
- self.update_metadata(user_id, tenant_id, metadata_ref)
-
- def remove_role_from_user_and_project(self, user_id, tenant_id, role_id):
- try:
- metadata_ref = self.get_metadata(user_id, tenant_id)
- roles = set(metadata_ref.get('roles', []))
- if role_id not in roles:
- raise exception.RoleNotFound(message=_(
- 'Cannot remove role that has not been granted, %s') %
- role_id)
- roles.remove(role_id)
- metadata_ref['roles'] = list(roles)
- if len(roles):
- self.update_metadata(user_id, tenant_id, metadata_ref)
- else:
- session = self.get_session()
- q = session.query(UserProjectGrant)
- q = q.filter_by(user_id=user_id)
- q = q.filter_by(project_id=tenant_id)
- q.delete()
- except exception.MetadataNotFound:
- msg = 'Cannot remove role that has not been granted, %s' % role_id
- raise exception.RoleNotFound(message=msg)
-
- # CRUD
- @sql.handle_conflicts(type='project')
- def create_project(self, tenant_id, tenant):
- tenant['name'] = clean.project_name(tenant['name'])
- session = self.get_session()
- with session.begin():
- tenant_ref = Project.from_dict(tenant)
- session.add(tenant_ref)
- session.flush()
- return tenant_ref.to_dict()
-
- @sql.handle_conflicts(type='project')
- def update_project(self, tenant_id, tenant):
- session = self.get_session()
-
- if 'name' in tenant:
- tenant['name'] = clean.project_name(tenant['name'])
-
- with session.begin():
- tenant_ref = self._get_project(session, tenant_id)
- old_project_dict = tenant_ref.to_dict()
- for k in tenant:
- old_project_dict[k] = tenant[k]
- new_project = Project.from_dict(old_project_dict)
- for attr in Project.attributes:
- if attr != 'id':
- setattr(tenant_ref, attr, getattr(new_project, attr))
- tenant_ref.extra = new_project.extra
- session.flush()
- return tenant_ref.to_dict(include_extra_dict=True)
-
- @sql.handle_conflicts(type='project')
- def delete_project(self, tenant_id):
- session = self.get_session()
-
- with session.begin():
- tenant_ref = self._get_project(session, tenant_id)
-
- q = session.query(UserProjectGrant)
- q = q.filter_by(project_id=tenant_id)
- q.delete(False)
-
- q = session.query(UserProjectGrant)
- q = q.filter_by(project_id=tenant_id)
- q.delete(False)
-
- q = session.query(GroupProjectGrant)
- q = q.filter_by(project_id=tenant_id)
- q.delete(False)
-
- session.delete(tenant_ref)
- session.flush()
-
- @sql.handle_conflicts(type='metadata')
- def create_metadata(self, user_id, tenant_id, metadata,
- domain_id=None, group_id=None):
- session = self.get_session()
- with session.begin():
- if user_id:
- if tenant_id:
- session.add(UserProjectGrant(user_id=user_id,
- project_id=tenant_id,
- data=metadata))
- elif domain_id:
- session.add(UserDomainGrant(user_id=user_id,
- domain_id=domain_id,
- data=metadata))
- elif group_id:
- if tenant_id:
- session.add(GroupProjectGrant(group_id=group_id,
- project_id=tenant_id,
- data=metadata))
- elif domain_id:
- session.add(GroupDomainGrant(group_id=group_id,
- domain_id=domain_id,
- data=metadata))
- session.flush()
- return metadata
-
- @sql.handle_conflicts(type='metadata')
- def update_metadata(self, user_id, tenant_id, metadata,
- domain_id=None, group_id=None):
- session = self.get_session()
- with session.begin():
- if user_id:
- if tenant_id:
- q = session.query(UserProjectGrant)
- q = q.filter_by(user_id=user_id)
- q = q.filter_by(project_id=tenant_id)
- elif domain_id:
- q = session.query(UserDomainGrant)
- q = q.filter_by(user_id=user_id)
- q = q.filter_by(domain_id=domain_id)
- elif group_id:
- if tenant_id:
- q = session.query(GroupProjectGrant)
- q = q.filter_by(group_id=group_id)
- q = q.filter_by(project_id=tenant_id)
- elif domain_id:
- q = session.query(GroupDomainGrant)
- q = q.filter_by(group_id=group_id)
- q = q.filter_by(domain_id=domain_id)
- metadata_ref = q.first()
- data = metadata_ref.data.copy()
- data.update(metadata)
- metadata_ref.data = data
- session.flush()
- return metadata_ref
-
- # domain crud
-
- @sql.handle_conflicts(type='domain')
- def create_domain(self, domain_id, domain):
- session = self.get_session()
- with session.begin():
- ref = Domain.from_dict(domain)
- session.add(ref)
- session.flush()
- return ref.to_dict()
-
- def list_domains(self):
- session = self.get_session()
- refs = session.query(Domain).all()
- return [ref.to_dict() for ref in refs]
-
- def _get_domain(self, session, domain_id):
- ref = session.query(Domain).get(domain_id)
- if ref is None:
- raise exception.DomainNotFound(domain_id=domain_id)
- return ref
-
- def get_domain(self, domain_id):
- session = self.get_session()
- return self._get_domain(session, domain_id).to_dict()
-
- def get_domain_by_name(self, domain_name):
- session = self.get_session()
- try:
- ref = session.query(Domain).filter_by(name=domain_name).one()
- except sql.NotFound:
- raise exception.DomainNotFound(domain_id=domain_name)
- return ref.to_dict()
-
- @sql.handle_conflicts(type='domain')
- def update_domain(self, domain_id, domain):
- session = self.get_session()
- with session.begin():
- ref = self._get_domain(session, domain_id)
- old_dict = ref.to_dict()
- for k in domain:
- old_dict[k] = domain[k]
- new_domain = Domain.from_dict(old_dict)
- for attr in Domain.attributes:
- if attr != 'id':
- setattr(ref, attr, getattr(new_domain, attr))
- ref.extra = new_domain.extra
- session.flush()
- return ref.to_dict()
-
- def delete_domain(self, domain_id):
- session = self.get_session()
- with session.begin():
- ref = self._get_domain(session, domain_id)
- session.delete(ref)
- session.flush()
-
- def list_user_projects(self, user_id):
- session = self.get_session()
- user = self.get_user(user_id)
- metadata_refs = session\
- .query(UserProjectGrant)\
- .filter_by(user_id=user_id)
- project_ids = set([x.project_id for x in metadata_refs
- if x.data.get('roles')])
- if user.get('project_id'):
- project_ids.add(user['project_id'])
-
- # FIXME(dolph): this should be removed with proper migrations
- if user.get('tenant_id'):
- project_ids.add(user['tenant_id'])
-
- return [self.get_project(x) for x in project_ids]
+ return identity.filter_user(user_ref.to_dict())
# user crud
@@ -742,20 +217,13 @@ class Identity(sql.Base, identity.Driver):
with session.begin():
ref = self._get_user(session, user_id)
- q = session.query(UserProjectGrant)
- q = q.filter_by(user_id=user_id)
- q.delete(False)
-
- q = session.query(UserDomainGrant)
- q = q.filter_by(user_id=user_id)
- q.delete(False)
-
q = session.query(UserGroupMembership)
q = q.filter_by(user_id=user_id)
q.delete(False)
session.delete(ref)
session.flush()
+ self.assignment_api.delete_user(user_id)
# group crud
@@ -806,92 +274,10 @@ class Identity(sql.Base, identity.Driver):
with session.begin():
ref = self._get_group(session, group_id)
- q = session.query(GroupProjectGrant)
- q = q.filter_by(group_id=group_id)
- q.delete(False)
-
- q = session.query(GroupDomainGrant)
- q = q.filter_by(group_id=group_id)
- q.delete(False)
-
q = session.query(UserGroupMembership)
q = q.filter_by(group_id=group_id)
q.delete(False)
session.delete(ref)
session.flush()
-
- # role crud
-
- @sql.handle_conflicts(type='role')
- def create_role(self, role_id, role):
- session = self.get_session()
- with session.begin():
- ref = Role.from_dict(role)
- session.add(ref)
- session.flush()
- return ref.to_dict()
-
- def list_roles(self):
- session = self.get_session()
- refs = session.query(Role).all()
- return [ref.to_dict() for ref in refs]
-
- def _get_role(self, session, role_id):
- ref = session.query(Role).get(role_id)
- if ref is None:
- raise exception.RoleNotFound(role_id=role_id)
- return ref
-
- def get_role(self, role_id):
- session = self.get_session()
- return self._get_role(session, role_id).to_dict()
-
- @sql.handle_conflicts(type='role')
- def update_role(self, role_id, role):
- session = self.get_session()
- with session.begin():
- ref = self._get_role(session, role_id)
- old_dict = ref.to_dict()
- for k in role:
- old_dict[k] = role[k]
- new_role = Role.from_dict(old_dict)
- for attr in Role.attributes:
- if attr != 'id':
- setattr(ref, attr, getattr(new_role, attr))
- ref.extra = new_role.extra
- session.flush()
- return ref.to_dict()
-
- def delete_role(self, role_id):
- session = self.get_session()
-
- with session.begin():
- ref = self._get_role(session, role_id)
- for metadata_ref in session.query(UserProjectGrant):
- try:
- self.delete_grant(role_id, user_id=metadata_ref.user_id,
- project_id=metadata_ref.project_id)
- except exception.RoleNotFound:
- pass
- for metadata_ref in session.query(UserDomainGrant):
- try:
- self.delete_grant(role_id, user_id=metadata_ref.user_id,
- domain_id=metadata_ref.domain_id)
- except exception.RoleNotFound:
- pass
- for metadata_ref in session.query(GroupProjectGrant):
- try:
- self.delete_grant(role_id, group_id=metadata_ref.group_id,
- project_id=metadata_ref.project_id)
- except exception.RoleNotFound:
- pass
- for metadata_ref in session.query(GroupDomainGrant):
- try:
- self.delete_grant(role_id, group_id=metadata_ref.group_id,
- domain_id=metadata_ref.domain_id)
- except exception.RoleNotFound:
- pass
-
- session.delete(ref)
- session.flush()
+ self.assignment_api.delete_group(group_id)
diff --git a/keystone/identity/controllers.py b/keystone/identity/controllers.py
index f798e3dc..7ca1f8bf 100644
--- a/keystone/identity/controllers.py
+++ b/keystone/identity/controllers.py
@@ -16,6 +16,7 @@
"""Workflow Logic the Identity service."""
+import copy
import urllib
import urlparse
import uuid
@@ -402,6 +403,8 @@ class DomainV3(controller.V3Controller):
@controller.protected
def create_domain(self, context, domain):
+ self._require_attribute(domain, 'name')
+
ref = self._assign_unique_id(self._normalize_dict(domain))
ref = self.identity_api.create_domain(ref['id'], ref)
return DomainV3.wrap_member(context, ref)
@@ -543,6 +546,8 @@ class ProjectV3(controller.V3Controller):
@controller.protected
def create_project(self, context, project):
+ self._require_attribute(project, 'name')
+
ref = self._assign_unique_id(self._normalize_dict(project))
ref = self._normalize_domain_id(context, ref)
ref = self.identity_api.create_project(ref['id'], ref)
@@ -591,6 +596,8 @@ class UserV3(controller.V3Controller):
@controller.protected
def create_user(self, context, user):
+ self._require_attribute(user, 'name')
+
ref = self._assign_unique_id(self._normalize_dict(user))
ref = self._normalize_domain_id(context, ref)
ref = self.identity_api.create_user(ref['id'], ref)
@@ -662,6 +669,8 @@ class GroupV3(controller.V3Controller):
@controller.protected
def create_group(self, context, group):
+ self._require_attribute(group, 'name')
+
ref = self._assign_unique_id(self._normalize_dict(group))
ref = self._normalize_domain_id(context, ref)
ref = self.identity_api.create_group(ref['id'], ref)
@@ -712,6 +721,8 @@ class RoleV3(controller.V3Controller):
@controller.protected
def create_role(self, context, role):
+ self._require_attribute(role, 'name')
+
ref = self._assign_unique_id(self._normalize_dict(role))
ref = self.identity_api.create_role(ref['id'], ref)
return RoleV3.wrap_member(context, ref)
@@ -747,6 +758,11 @@ class RoleV3(controller.V3Controller):
msg = 'Specify a user or group, not both'
raise exception.ValidationError(msg)
+ def _check_if_inherited(self, context):
+ return (CONF.os_inherit.enabled and
+ context['path'].startswith('/OS-INHERIT') and
+ context['path'].endswith('/inherited_to_projects'))
+
@controller.protected
def create_grant(self, context, role_id, user_id=None, group_id=None,
domain_id=None, project_id=None):
@@ -755,7 +771,8 @@ class RoleV3(controller.V3Controller):
self._require_user_xor_group(user_id, group_id)
self.identity_api.create_grant(
- role_id, user_id, group_id, domain_id, project_id)
+ role_id, user_id, group_id, domain_id, project_id,
+ self._check_if_inherited(context))
@controller.protected
def list_grants(self, context, user_id=None, group_id=None,
@@ -765,7 +782,8 @@ class RoleV3(controller.V3Controller):
self._require_user_xor_group(user_id, group_id)
refs = self.identity_api.list_grants(
- user_id, group_id, domain_id, project_id)
+ user_id, group_id, domain_id, project_id,
+ self._check_if_inherited(context))
return RoleV3.wrap_collection(context, refs)
@controller.protected
@@ -776,7 +794,8 @@ class RoleV3(controller.V3Controller):
self._require_user_xor_group(user_id, group_id)
self.identity_api.get_grant(
- role_id, user_id, group_id, domain_id, project_id)
+ role_id, user_id, group_id, domain_id, project_id,
+ self._check_if_inherited(context))
@controller.protected
def revoke_grant(self, context, role_id, user_id=None, group_id=None,
@@ -786,7 +805,8 @@ class RoleV3(controller.V3Controller):
self._require_user_xor_group(user_id, group_id)
self.identity_api.delete_grant(
- role_id, user_id, group_id, domain_id, project_id)
+ role_id, user_id, group_id, domain_id, project_id,
+ self._check_if_inherited(context))
# Now delete any tokens for this user or, in the case of a group,
# tokens from all the uses who are members of this group.
@@ -794,3 +814,330 @@ class RoleV3(controller.V3Controller):
self._delete_tokens_for_user(user_id)
else:
self._delete_tokens_for_group(group_id)
+
+
+class RoleAssignmentV3(controller.V3Controller):
+
+ # TODO(henry-nash): The current implementation does not provide a full
+ # first class entity for role-assignment. There is no role_assignment_id
+ # and only the list_role_assignment call is supported. Further, since it
+ # is not a first class entity, the links for the individual entities
+ # reference the individual role grant APIs.
+
+ collection_name = 'role_assignments'
+ member_name = 'role_assignment'
+
+ @classmethod
+ def wrap_member(cls, context, ref):
+ # NOTE(henry-nash): Since we are not yet a true collection, we override
+ # the wrapper as have already included the links in the entities
+ pass
+
+ def _format_entity(self, entity):
+ """Format an assignment entity for API response.
+
+ The driver layer returns entities as dicts containing the ids of the
+ actor (e.g. user or group), target (e.g. domain or project) and role.
+ If it is an inherited role, then this is also indicated. Examples:
+
+ {'user_id': user_id,
+ 'project_id': domain_id,
+ 'role_id': role_id}
+
+ or, for an inherited role:
+
+ {'user_id': user_id,
+ 'domain_id': domain_id,
+ 'role_id': role_id,
+ 'inherited_to_projects': true}
+
+ This function maps this into the format to be returned via the API,
+ e.g. for the second example above:
+
+ {
+ 'user': {
+ {'id': user_id}
+ },
+ 'scope': {
+ 'domain': {
+ {'id': domain_id}
+ },
+ 'OS-INHERIT:inherited_to': 'projects
+ },
+ 'role': {
+ {'id': role_id}
+ },
+ 'links': {
+ 'assignment': '/domains/domain_id/users/user_id/roles/'
+ 'role_id/inherited_to_projects'
+ }
+ }
+
+ """
+
+ formatted_entity = {}
+ suffix = ""
+ if 'user_id' in entity:
+ formatted_entity['user'] = {'id': entity['user_id']}
+ actor_link = 'users/%s' % entity['user_id']
+ if 'group_id' in entity:
+ formatted_entity['group'] = {'id': entity['group_id']}
+ actor_link = 'groups/%s' % entity['group_id']
+ if 'role_id' in entity:
+ formatted_entity['role'] = {'id': entity['role_id']}
+ if 'project_id' in entity:
+ formatted_entity['scope'] = (
+ {'project': {'id': entity['project_id']}})
+ target_link = '/projects/%s' % entity['project_id']
+ if 'domain_id' in entity:
+ formatted_entity['scope'] = (
+ {'domain': {'id': entity['domain_id']}})
+ if 'inherited_to_projects' in entity:
+ formatted_entity['scope']['OS-INHERIT:inherited_to'] = (
+ 'projects')
+ target_link = '/OS-INHERIT/domains/%s' % entity['domain_id']
+ suffix = '/inherited_to_projects'
+ else:
+ target_link = '/domains/%s' % entity['domain_id']
+ formatted_entity.setdefault('links', {})
+ formatted_entity['links']['assignment'] = (
+ self.base_url('%(target)s/%(actor)s/roles/%(role)s%(suffix)s' % {
+ 'target': target_link,
+ 'actor': actor_link,
+ 'role': entity['role_id'],
+ 'suffix': suffix}))
+
+ return formatted_entity
+
+ def _expand_indirect_assignments(self, refs):
+ """Processes entity list into all-direct assignments.
+
+ For any group role assignments in the list, create a role assignment
+ entity for each member of that group, and then remove the group
+ assignment entity itself from the list.
+
+ If the OS-INHERIT extension is enabled, then honor any inherited
+ roles on the domain by creating the equivalent on all projects
+ owned by the domain.
+
+ For any new entity created by virtue of group membership, add in an
+ additional link to that membership.
+
+ """
+ def _get_group_members(ref):
+ """Get a list of group members.
+
+ Get the list of group members. If this fails with
+ GroupNotFound, then log this as a warning, but allow
+ overall processing to continue.
+
+ """
+ try:
+ members = self.identity_api.list_users_in_group(
+ ref['group']['id'])
+ except exception.GroupNotFound:
+ members = []
+ # The group is missing, which should not happen since
+ # group deletion should remove any related assignments, so
+ # log a warning
+ if 'domain' in ref:
+ target = 'Domain: %s' % ref['domain'].get('domain_id')
+ elif 'project' in ref:
+ target = 'Project: %s' % ref['project'].get('project_id')
+ else:
+ # Should always be a domain or project, but since to get
+ # here things have gone astray, let's be cautious.
+ target = 'Unknown'
+ LOG.warning(
+ _('Group %(group)s not found for role-assignment - '
+ '%(target)s with Role: %(role)s') % {
+ 'group': ref['group_id'], 'target': target,
+ 'role': ref.get('role_id')})
+ return members
+
+ def _build_user_assignment_equivalent_of_group(
+ user, group_id, template):
+ """Create a user assignment equivalent to the group one.
+
+ The template has had the 'group' entity removed, so
+ substitute a 'user' one. The 'assignment' link stays as it is,
+ referring to the group assignment that led to this role.
+ A 'membership' link is added that refers to this particular
+ user's membership of this group.
+
+ """
+ user_entry = copy.deepcopy(template)
+ user_entry['user'] = {'id': user['id']}
+ user_entry['links']['membership'] = (
+ self.base_url('/groups/%s/users/%s' %
+ (group_id, user['id'])))
+ return user_entry
+
+ def _build_project_equivalent_of_user_domain_role(
+ project_id, domain_id, template):
+ """Create a user project assignment equivalent to the domain one.
+
+ The template has had the 'domain' entity removed, so
+ substitute a 'project' one, modifying the 'assignment' link
+ to match.
+
+ """
+ project_entry = copy.deepcopy(template)
+ project_entry['scope']['project'] = {'id': project_id}
+ project_entry['links']['assignment'] = (
+ self.base_url(
+ '/OS-INHERIT/domains/%s/users/%s/roles/%s'
+ '/inherited_to_projects' % (
+ domain_id, project_entry['user']['id'],
+ project_entry['role']['id'])))
+ return project_entry
+
+ def _build_project_equivalent_of_group_domain_role(
+ user_id, group_id, project_id, domain_id, template):
+ """Create a user project equivalent to the domain group one.
+
+ The template has had the 'domain' and 'group' entities removed, so
+ substitute a 'user-project' one, modifying the 'assignment' link
+ to match.
+
+ """
+ project_entry = copy.deepcopy(template)
+ project_entry['user'] = {'id': user_id}
+ project_entry['scope']['project'] = {'id': project_id}
+ project_entry['links']['assignment'] = (
+ self.base_url('/OS-INHERIT/domains/%s/groups/%s/roles/%s'
+ '/inherited_to_projects' % (
+ domain_id, group_id,
+ project_entry['role']['id'])))
+ project_entry['links']['membership'] = (
+ self.base_url('/groups/%s/users/%s' %
+ (group_id, user_id)))
+ return project_entry
+
+ # Scan the list of entities for any assignments that need to be
+ # expanded.
+ #
+ # If the OS-INERIT extension is enabled, the refs lists may
+ # contain roles to be inherited from domain to project, so expand
+ # these as well into project equivalents
+ #
+ # For any regular group entries, expand these into user entries based
+ # on membership of that group.
+ #
+ # Due to the potentially large expansions, rather than modify the
+ # list we are enumerating, we build a new one as we go.
+ #
+
+ new_refs = []
+ for r in refs:
+ if 'OS-INHERIT:inherited_to' in r['scope']:
+ # It's an inherited domain role - so get the list of projects
+ # owned by this domain. A domain scope is guaranteed since we
+ # checked this when we built the refs list
+ project_ids = (
+ [x['id'] for x in self.assignment_api.list_projects(
+ r['scope']['domain']['id'])])
+ base_entry = copy.deepcopy(r)
+ domain_id = base_entry['scope']['domain']['id']
+ base_entry['scope'].pop('domain')
+ # For each project, create an equivalent role assignment
+ for p in project_ids:
+ # If it's a group assignment, then create equivalent user
+ # roles based on membership of the group
+ if 'group' in base_entry:
+ members = _get_group_members(base_entry)
+ sub_entry = copy.deepcopy(base_entry)
+ group_id = sub_entry['group']['id']
+ sub_entry.pop('group')
+ for m in members:
+ new_entry = (
+ _build_project_equivalent_of_group_domain_role(
+ m['id'], group_id, p,
+ domain_id, sub_entry))
+ new_refs.append(new_entry)
+ else:
+ new_entry = (
+ _build_project_equivalent_of_user_domain_role(
+ p, domain_id, base_entry))
+ new_refs.append(new_entry)
+ elif 'group' in r:
+ # It's a non-inherited group role assignment, so get the list
+ # of members.
+ members = _get_group_members(r)
+
+ # Now replace that group role assignment entry with an
+ # equivalent user role assignment for each of the group members
+ base_entry = copy.deepcopy(r)
+ group_id = base_entry['group']['id']
+ base_entry.pop('group')
+ for m in members:
+ user_entry = _build_user_assignment_equivalent_of_group(
+ m, group_id, base_entry)
+ new_refs.append(user_entry)
+ else:
+ new_refs.append(r)
+
+ return new_refs
+
+ def _query_filter_is_true(self, filter_value):
+ """Determine if bool query param is 'True'.
+
+ We treat this the same way as we do for policy
+ enforcement:
+
+ {bool_param}=0 is treated as False
+
+ Any other value is considered to be equivalent to
+ True, including the absence of a value
+
+ """
+
+ if (isinstance(filter_value, basestring) and
+ filter_value == '0'):
+ val = False
+ else:
+ val = True
+ return val
+
+ def _filter_inherited(self, entry):
+ if ('inherited_to_projects' in entry and
+ not CONF.os_inherit.enabled):
+ return False
+ else:
+ return True
+
+ @controller.filterprotected('group.id', 'role.id',
+ 'scope.domain.id', 'scope.project.id',
+ 'scope.OS-INHERIT:inherited_to', 'user.id')
+ def list_role_assignments(self, context, filters):
+
+ # TODO(henry-nash): This implementation uses the standard filtering
+ # in the V3.wrap_collection. Given the large number of individual
+ # assignments, this is pretty inefficient. An alternative would be
+ # to pass the filters into the driver call, so that the list size is
+ # kept a minimum.
+
+ refs = self.identity_api.list_role_assignments()
+ formatted_refs = (
+ [self._format_entity(x) for x in refs
+ if self._filter_inherited(x)])
+
+ if ('effective' in context['query_string'] and
+ self._query_filter_is_true(
+ context['query_string']['effective'])):
+
+ formatted_refs = self._expand_indirect_assignments(formatted_refs)
+
+ return self.wrap_collection(context, formatted_refs, filters)
+
+ @controller.protected
+ def get_role_assignment(self, context):
+ raise exception.NotImplemented()
+
+ @controller.protected
+ def update_role_assignment(self, context):
+ raise exception.NotImplemented()
+
+ @controller.protected
+ def delete_role_assignment(self, context):
+ raise exception.NotImplemented()
diff --git a/keystone/identity/core.py b/keystone/identity/core.py
index a254470e..b2b3eaf0 100644
--- a/keystone/identity/core.py
+++ b/keystone/identity/core.py
@@ -52,6 +52,7 @@ def filter_user(user_ref):
@dependency.provider('identity_api')
+@dependency.requires('assignment_api')
class Manager(manager.Manager):
"""Default pivot point for the Identity backend.
@@ -63,15 +64,6 @@ class Manager(manager.Manager):
def __init__(self):
super(Manager, self).__init__(CONF.identity.driver)
- def authenticate(self, user_id=None, tenant_id=None, password=None):
- """Authenticate a given user and password and
- authorize them for a tenant.
- :returns: (user_ref, tenant_ref, metadata_ref)
- :raises: AssertionError
- """
- user_ref = self.driver.authenticate_user(user_id, password)
- return self.driver.authorize_for_project(user_ref, tenant_id)
-
def create_user(self, user_id, user_ref):
user = user_ref.copy()
user['name'] = clean.user_name(user['name'])
@@ -97,288 +89,133 @@ class Manager(manager.Manager):
tenant.setdefault('enabled', True)
tenant['enabled'] = clean.project_enabled(tenant['enabled'])
tenant.setdefault('description', '')
- return self.driver.create_project(tenant_id, tenant)
+ return self.assignment_api.create_project(tenant_id, tenant)
def update_project(self, tenant_id, tenant_ref):
tenant = tenant_ref.copy()
if 'enabled' in tenant:
tenant['enabled'] = clean.project_enabled(tenant['enabled'])
- return self.driver.update_project(tenant_id, tenant)
-
-
-class Driver(object):
- """Interface description for an Identity driver."""
-
- def authenticate_user(self, user_id, password):
- """Authenticate a given user and password.
- :returns: user_ref
- :raises: AssertionError
- """
- raise exception.NotImplemented()
-
- def authorize_for_project(self, tenant_id, user_ref):
- """Authenticate a given user for a tenant.
- :returns: (user_ref, tenant_ref, metadata_ref)
- :raises: AssertionError
- """
- raise exception.NotImplemented()
+ return self.assignment_api.update_project(tenant_id, tenant)
def get_project_by_name(self, tenant_name, domain_id):
- """Get a tenant by name.
-
- :returns: tenant_ref
- :raises: keystone.exception.ProjectNotFound
-
- """
- raise exception.NotImplemented()
-
- def get_user_by_name(self, user_name, domain_id):
- """Get a user by name.
-
- :returns: user_ref
- :raises: keystone.exception.UserNotFound
-
- """
- raise exception.NotImplemented()
-
- def add_user_to_project(self, tenant_id, user_id):
- """Add user to a tenant by creating a default role relationship.
-
- :raises: keystone.exception.ProjectNotFound,
- keystone.exception.UserNotFound
+ return self.assignment_api.get_project_by_name(tenant_name, domain_id)
- """
- self.add_role_to_user_and_project(user_id,
- tenant_id,
- config.CONF.member_role_id)
-
- def remove_user_from_project(self, tenant_id, user_id):
- """Remove user from a tenant
+ def get_project(self, tenant_id):
+ return self.assignment_api.get_project(tenant_id)
- :raises: keystone.exception.ProjectNotFound,
- keystone.exception.UserNotFound
+ def list_projects(self, domain_id=None):
+ return self.assignment_api.list_projects(domain_id)
- """
- roles = self.get_roles_for_user_and_project(user_id, tenant_id)
- if not roles:
- raise exception.NotFound(tenant_id)
- for role_id in roles:
- self.remove_role_from_user_and_project(user_id, tenant_id, role_id)
-
- def get_project_users(self, tenant_id):
- """Lists all users with a relationship to the specified project.
-
- :returns: a list of user_refs or an empty set.
- :raises: keystone.exception.ProjectNotFound
+ def get_role(self, role_id):
+ return self.assignment_api.get_role(role_id)
- """
- raise exception.NotImplemented()
+ def list_roles(self):
+ return self.assignment_api.list_roles()
def get_projects_for_user(self, user_id):
- """Get the tenants associated with a given user.
+ return self.assignment_api.get_projects_for_user(user_id)
- :returns: a list of tenant_id's.
- :raises: keystone.exception.UserNotFound
-
- """
- raise exception.NotImplemented()
+ def get_project_users(self, tenant_id):
+ return self.assignment_api.get_project_users(tenant_id)
def get_roles_for_user_and_project(self, user_id, tenant_id):
- """Get the roles associated with a user within given tenant.
-
- :returns: a list of role ids.
- :raises: keystone.exception.UserNotFound,
- keystone.exception.ProjectNotFound
-
- """
- raise exception.NotImplemented()
+ return self.assignment_api.get_roles_for_user_and_project(
+ user_id, tenant_id)
def get_roles_for_user_and_domain(self, user_id, domain_id):
- """Get the roles associated with a user within given domain.
-
- :returns: a list of role ids.
- :raises: keystone.exception.UserNotFound,
- keystone.exception.ProjectNotFound
-
- """
-
- def update_metadata_for_group_domain_roles(self, metadata_ref,
- user_id, domain_id):
- group_refs = self.list_groups_for_user(user_id=user_id)
- for x in group_refs:
- try:
- metadata_ref.update(
- self.get_metadata(group_id=x['id'],
- domain_id=domain_id))
- except exception.MetadataNotFound:
- # no group grant, skip
- pass
-
- def update_metadata_for_user_domain_roles(self, metadata_ref,
- user_id, domain_id):
- try:
- metadata_ref.update(self.get_metadata(user_id=user_id,
- domain_id=domain_id))
- except exception.MetadataNotFound:
- pass
-
- self.get_user(user_id)
- self.get_domain(domain_id)
- metadata_ref = {}
- update_metadata_for_user_domain_roles(self, metadata_ref,
- user_id, domain_id)
- update_metadata_for_group_domain_roles(self, metadata_ref,
- user_id, domain_id)
- return list(set(metadata_ref.get('roles', [])))
-
- def add_role_to_user_and_project(self, user_id, tenant_id, role_id):
- """Add a role to a user within given tenant.
-
- :raises: keystone.exception.UserNotFound,
- keystone.exception.ProjectNotFound,
- keystone.exception.RoleNotFound
- """
- raise exception.NotImplemented()
-
- def remove_role_from_user_and_project(self, user_id, tenant_id, role_id):
- """Remove a role from a user within given tenant.
-
- :raises: keystone.exception.UserNotFound,
- keystone.exception.ProjectNotFound,
- keystone.exception.RoleNotFound
+ return (self.assignment_api.get_roles_for_user_and_domain
+ (user_id, domain_id))
- """
- raise exception.NotImplemented()
-
- # metadata crud
- def get_metadata(self, user_id=None, tenant_id=None,
- domain_id=None, group_id=None):
- """Gets the metadata for the specified user/group on project/domain.
+ def _subrole_id_to_dn(self, role_id, tenant_id):
+ return self.assignment_api._subrole_id_to_dn(role_id, tenant_id)
- :raises: keystone.exception.MetadataNotFound
- :returns: metadata
-
- """
- raise exception.NotImplemented()
+ def add_role_to_user_and_project(self, user_id,
+ tenant_id, role_id):
+ return (self.assignment_api.add_role_to_user_and_project
+ (user_id, tenant_id, role_id))
- def create_metadata(self, user_id, tenant_id, metadata,
- domain_id=None, group_id=None):
- """Creates the metadata for the specified user/group on project/domain.
-
- :returns: metadata created
+ def create_role(self, role_id, role):
+ return self.assignment_api.create_role(role_id, role)
- """
- raise exception.NotImplemented()
+ def delete_role(self, role_id):
+ return self.assignment_api.delete_role(role_id)
- def update_metadata(self, user_id, tenant_id, metadata,
- domain_id=None, group_id=None):
- """Updates the metadata for the specified user/group on project/domain.
+ def delete_project(self, tenant_id):
+ return self.assignment_api.delete_project(tenant_id)
- :returns: metadata updated
+ def remove_role_from_user_and_project(self, user_id,
+ tenant_id, role_id):
+ return (self.assignment_api.remove_role_from_user_and_project
+ (user_id, tenant_id, role_id))
- """
- raise exception.NotImplemented()
+ def update_role(self, role_id, role):
+ return self.assignment_api.update_role(role_id, role)
+
+ def create_grant(self, role_id, user_id=None, group_id=None,
+ domain_id=None, project_id=None,
+ inherited_to_projects=False):
+ return (self.assignment_api.create_grant
+ (role_id, user_id, group_id, domain_id, project_id,
+ inherited_to_projects))
+
+ def list_grants(self, user_id=None, group_id=None,
+ domain_id=None, project_id=None,
+ inherited_to_projects=False):
+ return (self.assignment_api.list_grants
+ (user_id, group_id, domain_id, project_id,
+ inherited_to_projects))
+
+ def get_grant(self, role_id, user_id=None, group_id=None,
+ domain_id=None, project_id=None,
+ inherited_to_projects=False):
+ return (self.assignment_api.get_grant
+ (role_id, user_id, group_id, domain_id, project_id,
+ inherited_to_projects))
+
+ def delete_grant(self, role_id, user_id=None, group_id=None,
+ domain_id=None, project_id=None,
+ inherited_to_projects=False):
+ return (self.assignment_api.delete_grant
+ (role_id, user_id, group_id, domain_id, project_id,
+ inherited_to_projects))
- # domain crud
def create_domain(self, domain_id, domain):
- """Creates a new domain.
-
- :raises: keystone.exception.Conflict
-
- """
- raise exception.NotImplemented()
-
- def list_domains(self):
- """List all domains in the system.
-
- :returns: a list of domain_refs or an empty list.
-
- """
- raise exception.NotImplemented()
-
- def get_domain(self, domain_id):
- """Get a domain by ID.
-
- :returns: domain_ref
- :raises: keystone.exception.DomainNotFound
-
- """
- raise exception.NotImplemented()
+ return self.assignment_api.create_domain(domain_id, domain)
def get_domain_by_name(self, domain_name):
- """Get a domain by name.
+ return self.assignment_api.get_domain_by_name(domain_name)
- :returns: domain_ref
- :raises: keystone.exception.DomainNotFound
-
- """
- raise exception.NotImplemented()
+ def get_domain(self, domain_id):
+ return self.assignment_api.get_domain(domain_id)
def update_domain(self, domain_id, domain):
- """Updates an existing domain.
-
- :raises: keystone.exception.DomainNotFound,
- keystone.exception.Conflict
-
- """
- raise exception.NotImplemented()
+ return self.assignment_api.update_domain(domain_id, domain)
def delete_domain(self, domain_id):
- """Deletes an existing domain.
-
- :raises: keystone.exception.DomainNotFound
-
- """
- raise exception.NotImplemented()
+ return self.assignment_api.delete_domain(domain_id)
- # project crud
- def create_project(self, project_id, project):
- """Creates a new project.
-
- :raises: keystone.exception.Conflict
-
- """
- raise exception.NotImplemented()
-
- def list_projects(self):
- """List all projects in the system.
-
- :returns: a list of project_refs or an empty list.
-
- """
- raise exception.NotImplemented()
+ def list_domains(self):
+ return self.assignment_api.list_domains()
def list_user_projects(self, user_id):
- """List all projects associated with a given user.
+ return self.assignment_api.list_user_projects(user_id)
- :returns: a list of project_refs or an empty list.
-
- """
- raise exception.NotImplemented()
-
- def get_project(self, project_id):
- """Get a project by ID.
-
- :returns: project_ref
- :raises: keystone.exception.ProjectNotFound
-
- """
- raise exception.NotImplemented()
-
- def update_project(self, project_id, project):
- """Updates an existing project.
-
- :raises: keystone.exception.ProjectNotFound,
- keystone.exception.Conflict
+ def add_user_to_project(self, tenant_id, user_id):
+ return self.assignment_api.add_user_to_project(tenant_id, user_id)
- """
- raise exception.NotImplemented()
+ def remove_user_from_project(self, tenant_id, user_id):
+ return self.assignment_api.remove_user_from_project(tenant_id, user_id)
- def delete_project(self, project_id):
- """Deletes an existing project.
+ def list_role_assignments(self):
+ return self.assignment_api.list_role_assignments()
- :raises: keystone.exception.ProjectNotFound
+class Driver(object):
+ """Interface description for an Identity driver."""
+ def authenticate(self, user_id, password):
+ """Authenticate a given user and password.
+ :returns: user_ref
+ :raises: AssertionError
"""
raise exception.NotImplemented()
@@ -460,46 +297,11 @@ class Driver(object):
"""
raise exception.NotImplemented()
- # role crud
-
- def create_role(self, role_id, role):
- """Creates a new role.
-
- :raises: keystone.exception.Conflict
-
- """
- raise exception.NotImplemented()
-
- def list_roles(self):
- """List all roles in the system.
-
- :returns: a list of role_refs or an empty list.
-
- """
- raise exception.NotImplemented()
-
- def get_role(self, role_id):
- """Get a role by ID.
-
- :returns: role_ref
- :raises: keystone.exception.RoleNotFound
-
- """
- raise exception.NotImplemented()
-
- def update_role(self, role_id, role):
- """Updates an existing role.
-
- :raises: keystone.exception.RoleNotFound,
- keystone.exception.Conflict
-
- """
- raise exception.NotImplemented()
-
- def delete_role(self, role_id):
- """Deletes an existing role.
+ def get_user_by_name(self, user_name, domain_id):
+ """Get a user by name.
- :raises: keystone.exception.RoleNotFound
+ :returns: user_ref
+ :raises: keystone.exception.UserNotFound
"""
raise exception.NotImplemented()
@@ -555,3 +357,7 @@ class Driver(object):
"""
raise exception.NotImplemented()
+
+ #end of identity
+
+ # Assignments
diff --git a/keystone/identity/routers.py b/keystone/identity/routers.py
index 32eada5e..5f236842 100644
--- a/keystone/identity/routers.py
+++ b/keystone/identity/routers.py
@@ -16,6 +16,7 @@
"""WSGI Routers for the Identity service."""
from keystone.common import router
from keystone.common import wsgi
+from keystone import config
from keystone.identity import controllers
@@ -173,3 +174,48 @@ def append_v3_routers(mapper, routers):
controller=role_controller,
action='revoke_grant',
conditions=dict(method=['DELETE']))
+
+ if config.CONF.os_inherit.enabled:
+ mapper.connect(('/OS-INHERIT/domains/{domain_id}/users/{user_id}'
+ '/roles/{role_id}/inherited_to_projects'),
+ controller=role_controller,
+ action='create_grant',
+ conditions=dict(method=['PUT']))
+ mapper.connect(('/OS-INHERIT/domains/{domain_id}/groups/{group_id}'
+ '/roles/{role_id}/inherited_to_projects'),
+ controller=role_controller,
+ action='create_grant',
+ conditions=dict(method=['PUT']))
+ mapper.connect(('/OS-INHERIT/domains/{domain_id}/users/{user_id}'
+ '/roles/{role_id}/inherited_to_projects'),
+ controller=role_controller,
+ action='check_grant',
+ conditions=dict(method=['HEAD']))
+ mapper.connect(('/OS-INHERIT/domains/{domain_id}/groups/{group_id}'
+ '/roles/{role_id}/inherited_to_projects'),
+ controller=role_controller,
+ action='check_grant',
+ conditions=dict(method=['HEAD']))
+ mapper.connect(('/OS-INHERIT/domains/{domain_id}/users/{user_id}'
+ '/roles/inherited_to_projects'),
+ controller=role_controller,
+ action='list_grants',
+ conditions=dict(method=['GET']))
+ mapper.connect(('/OS-INHERIT/domains/{domain_id}/groups/{group_id}'
+ '/roles/inherited_to_projects'),
+ controller=role_controller,
+ action='list_grants',
+ conditions=dict(method=['GET']))
+ mapper.connect(('/OS-INHERIT/domains/{domain_id}/users/{user_id}'
+ '/roles/{role_id}/inherited_to_projects'),
+ controller=role_controller,
+ action='revoke_grant',
+ conditions=dict(method=['DELETE']))
+ mapper.connect(('/OS-INHERIT/domains/{domain_id}/groups/{group_id}'
+ '/roles/{role_id}/inherited_to_projects'),
+ controller=role_controller,
+ action='revoke_grant',
+ conditions=dict(method=['DELETE']))
+ routers.append(
+ router.Router(controllers.RoleAssignmentV3(),
+ 'role_assignments', 'role_assignment'))
diff --git a/keystone/locale/bg_BG/LC_MESSAGES/keystone.po b/keystone/locale/bg_BG/LC_MESSAGES/keystone.po
index 13eb63b9..c6890424 100644
--- a/keystone/locale/bg_BG/LC_MESSAGES/keystone.po
+++ b/keystone/locale/bg_BG/LC_MESSAGES/keystone.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Keystone\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2013-06-17 17:09+0000\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
"PO-Revision-Date: 2013-05-17 16:06+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
"Language-Team: Bulgarian (Bulgaria) "
@@ -16,7 +16,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.6\n"
+"Generated-By: Babel 1.3\n"
#: keystone/clean.py:23
#, python-format
@@ -38,62 +38,224 @@ msgstr ""
msgid "%(property_name)s is not a %(display_expected_type)s"
msgstr ""
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
#: keystone/test.py:117
#, python-format
msgid "Failed to checkout %s"
msgstr ""
-#: keystone/auth/controllers.py:72
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr ""
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr ""
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
#, python-format
msgid "Project is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:78 keystone/auth/plugins/password.py:39
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
#, python-format
msgid "Domain is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:84 keystone/auth/plugins/password.py:45
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
#, python-format
msgid "User is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:265
+#: keystone/auth/controllers.py:262
msgid "Scoping to both domain and project is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:268
+#: keystone/auth/controllers.py:265
msgid "Scoping to both domain and trust is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:271
+#: keystone/auth/controllers.py:268
msgid "Scoping to both project and trust is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:333
-#, python-format
-msgid "Unable to lookup user %s"
-msgstr ""
-
-#: keystone/auth/controllers.py:363
+#: keystone/auth/controllers.py:353
msgid "User not found"
msgstr ""
-#: keystone/auth/token_factory.py:81
-msgid "User have no access to project"
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
msgstr ""
-#: keystone/auth/token_factory.py:96
-msgid "User have no access to domain"
-msgstr ""
-
-#: keystone/auth/token_factory.py:314 keystone/token/controllers.py:121
-msgid "Unable to sign token."
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
+#, python-format
+msgid "Unable to lookup user %s"
msgstr ""
-#: keystone/auth/token_factory.py:317 keystone/token/controllers.py:124
-#, python-format
-msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
msgstr ""
#: keystone/catalog/core.py:38
@@ -120,18 +282,18 @@ msgstr ""
msgid "Unable to open template file %s"
msgstr ""
-#: keystone/common/cms.py:42
+#: keystone/common/cms.py:26
#, python-format
msgid "Verify error: %s"
msgstr ""
-#: keystone/common/cms.py:134
+#: keystone/common/cms.py:118
msgid ""
"Signing error: Unable to load certificate - ensure you've configured PKI "
"with 'keystone-manage pki_setup'"
msgstr ""
-#: keystone/common/cms.py:138
+#: keystone/common/cms.py:122
#, python-format
msgid "Signing error: %s"
msgstr ""
@@ -150,31 +312,31 @@ msgstr ""
msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
msgstr ""
-#: keystone/common/controller.py:26
+#: keystone/common/controller.py:25
msgid "RBAC: Invalid token"
msgstr ""
-#: keystone/common/controller.py:36 keystone/common/controller.py:57
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
msgid "RBAC: Invalid user"
msgstr ""
-#: keystone/common/controller.py:42
+#: keystone/common/controller.py:45
msgid "RBAC: Proceeding without project"
msgstr ""
-#: keystone/common/controller.py:62
+#: keystone/common/controller.py:65
msgid "RBAC: Proceeding without tenant"
msgstr ""
-#: keystone/common/controller.py:92 keystone/common/controller.py:144
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
msgid "RBAC: Bypassing authorization"
msgstr ""
-#: keystone/common/controller.py:101 keystone/common/controller.py:142
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
msgid "RBAC: Authorization granted"
msgstr ""
-#: keystone/common/controller.py:131
+#: keystone/common/controller.py:134
#, python-format
msgid "RBAC: Adding query filter params (%s)"
msgstr ""
@@ -183,33 +345,69 @@ msgstr ""
msgid "Invalid token in normalize_domain_id"
msgstr ""
-#: keystone/common/utils.py:232
+#: keystone/common/utils.py:233
msgid ""
"Error setting up the debug environment. Verify that the option --debug-"
"url has the format <host>:<port> and that a debugger processes is "
"listening on that port."
msgstr ""
-#: keystone/common/wsgi.py:162
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
#, python-format
msgid "arg_dict: %s"
msgstr ""
-#: keystone/common/wsgi.py:186
+#: keystone/common/wsgi.py:243
#, python-format
msgid "Authorization failed. %(exception)s from %(remote_addr)s"
msgstr ""
-#: keystone/common/wsgi.py:429
+#: keystone/common/wsgi.py:487
msgid "The resource could not be found."
msgstr ""
-#: keystone/common/wsgi_server.py:72
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
#, python-format
msgid "Starting %(arg0)s on %(host)s:%(port)s"
msgstr ""
-#: keystone/common/wsgi_server.py:132
+#: keystone/common/environment/eventlet_server.py:113
msgid "Server error"
msgstr ""
@@ -242,13 +440,13 @@ msgid ""
"\"%(attr_map)s\" must use one of %(keys)s."
msgstr ""
-#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:596
-#: keystone/identity/backends/kvs.py:624
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
#, python-format
msgid "Duplicate name, %s."
msgstr ""
-#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:589
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
#, python-format
msgid "Duplicate ID, %s."
msgstr ""
@@ -436,12 +634,16 @@ msgstr ""
msgid "Search scope %s not implemented."
msgstr ""
-#: keystone/common/sql/core.py:205
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
#, python-format
msgid "Got mysql server has gone away: %s"
msgstr ""
-#: keystone/common/sql/legacy.py:180
+#: keystone/common/sql/legacy.py:188
#, python-format
msgid "Cannot migrate EC2 credential: %s"
msgstr ""
@@ -450,76 +652,68 @@ msgstr ""
msgid "version should be an integer"
msgstr ""
-#: keystone/common/sql/nova.py:62
+#: keystone/common/sql/nova.py:65
#, python-format
msgid "Create tenant %s"
msgstr ""
-#: keystone/common/sql/nova.py:79
+#: keystone/common/sql/nova.py:82
#, python-format
msgid "Create user %s"
msgstr ""
-#: keystone/common/sql/nova.py:88
+#: keystone/common/sql/nova.py:91
#, python-format
msgid "Add user %(user_id)s to tenant %(tenant_id)s"
msgstr ""
-#: keystone/common/sql/nova.py:97
+#: keystone/common/sql/nova.py:100
#, python-format
msgid "Ignoring existing role %s"
msgstr ""
-#: keystone/common/sql/nova.py:104
+#: keystone/common/sql/nova.py:107
#, python-format
msgid "Create role %s"
msgstr ""
-#: keystone/common/sql/nova.py:114
+#: keystone/common/sql/nova.py:117
#, python-format
msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
msgstr ""
-#: keystone/common/sql/nova.py:133
+#: keystone/common/sql/nova.py:136
#, python-format
msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
msgstr ""
-#: keystone/identity/backends/kvs.py:250 keystone/identity/backends/kvs.py:259
-msgid "User not found in group"
-msgstr ""
-
-#: keystone/identity/backends/sql.py:425
+#: keystone/identity/controllers.py:952
#, python-format
-msgid "Cannot remove role that has not been granted, %s"
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:82
-#, python-format
-msgid "Expected dict or list: %s"
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
+msgid "User not found in group"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:681
+#: keystone/identity/backends/ldap.py:189
#, python-format
-msgid "Role %s not found"
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
msgstr ""
-#: keystone/identity/backends/ldap/core.py:898
+#: keystone/identity/backends/ldap.py:334
msgid "Changing Name not supported by LDAP"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:911
+#: keystone/identity/backends/ldap.py:347
#, python-format
msgid "User %(user_id)s is already a member of group %(group_id)s"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:954
-#, python-format
-msgid ""
-"Group member '%(user_dn)s' not found in '%(group_dn)s'. The user should "
-"be removed from the group. The user will be ignored."
-msgstr ""
-
#: keystone/openstack/common/policy.py:394
#, python-format
msgid "Failed to understand rule %(rule)s"
@@ -535,21 +729,56 @@ msgstr ""
msgid "Failed to understand rule %(rule)r"
msgstr ""
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
#: keystone/policy/backends/rules.py:93
#, python-format
msgid "enforce %(action)s: %(credentials)s"
msgstr ""
-#: keystone/token/controllers.py:465 keystone/token/controllers.py:468
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
msgid "Token does not belong to specified tenant."
msgstr ""
-#: keystone/token/controllers.py:475
-msgid "Non-default domain is not supported"
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
msgstr ""
-#: keystone/token/controllers.py:483
-msgid "Domain scoped token is not supported"
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
msgstr ""
#: keystone/token/backends/memcache.py:144
@@ -574,3 +803,54 @@ msgstr ""
msgid "Unable to add token to revocation list."
msgstr ""
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
+#~ msgid "User have no access to project"
+#~ msgstr ""
+
+#~ msgid "User have no access to domain"
+#~ msgstr ""
+
+#~ msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+#~ msgstr ""
+
diff --git a/keystone/locale/bs/LC_MESSAGES/keystone.po b/keystone/locale/bs/LC_MESSAGES/keystone.po
new file mode 100644
index 00000000..8aee9ca5
--- /dev/null
+++ b/keystone/locale/bs/LC_MESSAGES/keystone.po
@@ -0,0 +1,848 @@
+# Bosnian translations for keystone.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the keystone project.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: Keystone\n"
+"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
+"PO-Revision-Date: 2013-07-29 22:01+0000\n"
+"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
+"Language-Team: Bosnian "
+"(http://www.transifex.com/projects/p/openstack/language/bs/)\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 1.3\n"
+
+#: keystone/clean.py:23
+#, python-format
+msgid "%s cannot be empty."
+msgstr ""
+
+#: keystone/clean.py:25
+#, python-format
+msgid "%(property_name)s cannot be less than %(min_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:29
+#, python-format
+msgid "%(property_name)s should not be greater than %(max_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:36
+#, python-format
+msgid "%(property_name)s is not a %(display_expected_type)s"
+msgstr ""
+
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
+#: keystone/test.py:117
+#, python-format
+msgid "Failed to checkout %s"
+msgstr ""
+
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr ""
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr ""
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
+#, python-format
+msgid "Project is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
+#, python-format
+msgid "Domain is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
+#, python-format
+msgid "User is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:262
+msgid "Scoping to both domain and project is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:265
+msgid "Scoping to both domain and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:268
+msgid "Scoping to both project and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:353
+msgid "User not found"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
+#, python-format
+msgid "Unable to lookup user %s"
+msgstr ""
+
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
+msgstr ""
+
+#: keystone/catalog/core.py:38
+#, python-format
+msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s"
+msgstr ""
+
+#: keystone/catalog/core.py:43
+#, python-format
+msgid ""
+"Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing "
+"brackets ?)"
+msgstr ""
+
+#: keystone/catalog/core.py:49
+#, python-format
+msgid ""
+"Malformed endpoint %s - incomplete format (are you "
+"missing a type notifier ?)"
+msgstr ""
+
+#: keystone/catalog/backends/templated.py:109
+#, python-format
+msgid "Unable to open template file %s"
+msgstr ""
+
+#: keystone/common/cms.py:26
+#, python-format
+msgid "Verify error: %s"
+msgstr ""
+
+#: keystone/common/cms.py:118
+msgid ""
+"Signing error: Unable to load certificate - ensure you've configured PKI "
+"with 'keystone-manage pki_setup'"
+msgstr ""
+
+#: keystone/common/cms.py:122
+#, python-format
+msgid "Signing error: %s"
+msgstr ""
+
+#: keystone/common/config.py:89
+#, python-format
+msgid "Unable to locate specified logging config file: %s"
+msgstr ""
+
+#: keystone/common/config.py:107
+msgid "Invalid syslog facility"
+msgstr ""
+
+#: keystone/common/controller.py:18
+#, python-format
+msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
+msgstr ""
+
+#: keystone/common/controller.py:25
+msgid "RBAC: Invalid token"
+msgstr ""
+
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
+msgid "RBAC: Invalid user"
+msgstr ""
+
+#: keystone/common/controller.py:45
+msgid "RBAC: Proceeding without project"
+msgstr ""
+
+#: keystone/common/controller.py:65
+msgid "RBAC: Proceeding without tenant"
+msgstr ""
+
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
+msgid "RBAC: Bypassing authorization"
+msgstr ""
+
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
+msgid "RBAC: Authorization granted"
+msgstr ""
+
+#: keystone/common/controller.py:134
+#, python-format
+msgid "RBAC: Adding query filter params (%s)"
+msgstr ""
+
+#: keystone/common/controller.py:322
+msgid "Invalid token in normalize_domain_id"
+msgstr ""
+
+#: keystone/common/utils.py:233
+msgid ""
+"Error setting up the debug environment. Verify that the option --debug-"
+"url has the format <host>:<port> and that a debugger processes is "
+"listening on that port."
+msgstr ""
+
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
+#, python-format
+msgid "arg_dict: %s"
+msgstr ""
+
+#: keystone/common/wsgi.py:243
+#, python-format
+msgid "Authorization failed. %(exception)s from %(remote_addr)s"
+msgstr ""
+
+#: keystone/common/wsgi.py:487
+msgid "The resource could not be found."
+msgstr ""
+
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
+#, python-format
+msgid "Starting %(arg0)s on %(host)s:%(port)s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:113
+msgid "Server error"
+msgstr ""
+
+#: keystone/common/ldap/core.py:79
+#, python-format
+msgid "Invalid LDAP deref option: %s. Choose one of: "
+msgstr ""
+
+#: keystone/common/ldap/core.py:87
+#, python-format
+msgid "Invalid LDAP TLS certs option: %(option). Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:99
+#, python-format
+msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:189
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%s\". Format must be "
+"<ldap_attribute>:<keystone_attribute>"
+msgstr ""
+
+#: keystone/common/ldap/core.py:195
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%(item)s\". Value "
+"\"%(attr_map)s\" must use one of %(keys)s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
+#, python-format
+msgid "Duplicate name, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
+#, python-format
+msgid "Duplicate ID, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:294
+#, python-format
+msgid "LDAP %s create"
+msgstr ""
+
+#: keystone/common/ldap/core.py:372
+#, python-format
+msgid "LDAP %s update"
+msgstr ""
+
+#: keystone/common/ldap/core.py:405
+#, python-format
+msgid "LDAP %s delete"
+msgstr ""
+
+#: keystone/common/ldap/core.py:430
+#, python-format
+msgid "LDAP init: url=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:431
+#, python-format
+msgid ""
+"LDAP init: use_tls=%(use_tls)s\n"
+"tls_cacertfile=%(tls_cacertfile)s\n"
+"tls_cacertdir=%(tls_cacertdir)s\n"
+"tls_req_cert=%(tls_req_cert)s\n"
+"tls_avail=%(tls_avail)s\n"
+msgstr ""
+
+#: keystone/common/ldap/core.py:450
+msgid "Invalid TLS / LDAPS combination"
+msgstr ""
+
+#: keystone/common/ldap/core.py:454
+#, python-format
+msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available"
+msgstr ""
+
+#: keystone/common/ldap/core.py:464
+#, python-format
+msgid "tls_cacertfile %s not found or is not a file"
+msgstr ""
+
+#: keystone/common/ldap/core.py:476
+#, python-format
+msgid "tls_cacertdir %s not found or is not a directory"
+msgstr ""
+
+#: keystone/common/ldap/core.py:483
+#, python-format
+msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:497
+#, python-format
+msgid "LDAP bind: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:508
+#, python-format
+msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:514
+#, python-format
+msgid ""
+"LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, "
+"attrs=%(attrlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:567
+msgid ""
+"LDAP Server does not support paging. Disable paging in keystone.conf to "
+"avoid this message."
+msgstr ""
+
+#: keystone/common/ldap/core.py:584
+#, python-format
+msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:590
+#, python-format
+msgid "LDAP delete: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:595
+#, python-format
+msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:146
+#, python-format
+msgid "FakeLdap initialize url=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:156
+#, python-format
+msgid "FakeLdap bind dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:163
+#, python-format
+msgid "FakeLdap bind fail: dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:170
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:175
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s does not match"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:190
+#, python-format
+msgid "FakeLdap add item: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:193
+#, python-format
+msgid "FakeLdap add item failed: dn=%s is already in store."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:207 keystone/common/ldap/fakeldap.py:221
+#, python-format
+msgid "FakeLdap delete item: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:211 keystone/common/ldap/fakeldap.py:225
+#, python-format
+msgid "FakeLdap delete item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:240
+#, python-format
+msgid "FakeLdap modify item: dn=%(dn)s attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:245
+#, python-format
+msgid "FakeLdap modify item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:262
+#, python-format
+msgid "FakeLdap modify item failed: item has no attribute \"%s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:273
+#, python-format
+msgid ""
+"FakeLdap modify item failed: item has no attribute \"%(k)s\" with value "
+"\"%(v)s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:279
+#, python-format
+msgid "FakeLdap modify item failed: unknown command %s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:281
+#, python-format
+msgid "modify_s action %s not implemented"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:300
+#, python-format
+msgid "FakeLdap search at dn=%(dn)s scope=%(scope)s query=%(query)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:306
+msgid "FakeLdap search fail: dn not found for SCOPE_BASE"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:320
+#, python-format
+msgid "Search scope %s not implemented."
+msgstr ""
+
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
+#, python-format
+msgid "Got mysql server has gone away: %s"
+msgstr ""
+
+#: keystone/common/sql/legacy.py:188
+#, python-format
+msgid "Cannot migrate EC2 credential: %s"
+msgstr ""
+
+#: keystone/common/sql/migration.py:47
+msgid "version should be an integer"
+msgstr ""
+
+#: keystone/common/sql/nova.py:65
+#, python-format
+msgid "Create tenant %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:82
+#, python-format
+msgid "Create user %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:91
+#, python-format
+msgid "Add user %(user_id)s to tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:100
+#, python-format
+msgid "Ignoring existing role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:107
+#, python-format
+msgid "Create role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:117
+#, python-format
+msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:136
+#, python-format
+msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/identity/controllers.py:952
+#, python-format
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
+msgstr ""
+
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
+msgid "User not found in group"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:189
+#, python-format
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:334
+msgid "Changing Name not supported by LDAP"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:347
+#, python-format
+msgid "User %(user_id)s is already a member of group %(group_id)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:394
+#, python-format
+msgid "Failed to understand rule %(rule)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:404
+#, python-format
+msgid "No handler for matches of kind %s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:679
+#, python-format
+msgid "Failed to understand rule %(rule)r"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
+#: keystone/policy/backends/rules.py:93
+#, python-format
+msgid "enforce %(action)s: %(credentials)s"
+msgstr ""
+
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
+msgid "Token does not belong to specified tenant."
+msgstr ""
+
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
+msgstr ""
+
+#: keystone/token/backends/memcache.py:144
+#, python-format
+msgid ""
+"Successful set of token-index-list for user-key \"%(user_key)s\", "
+"#%(count)d records"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:154
+#, python-format
+msgid ""
+"Failed to set token-index-list for user-key \"%(user_key)s\". Attempt "
+"%(cas_retry)d of %(cas_retry_max)d"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:163
+msgid "Unable to add token user list"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:172
+msgid "Unable to add token to revocation list."
+msgstr ""
+
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
diff --git a/keystone/locale/ca/LC_MESSAGES/keystone.po b/keystone/locale/ca/LC_MESSAGES/keystone.po
index c3c32221..110ea54c 100644
--- a/keystone/locale/ca/LC_MESSAGES/keystone.po
+++ b/keystone/locale/ca/LC_MESSAGES/keystone.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Keystone\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2013-06-17 17:09+0000\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
"PO-Revision-Date: 2012-11-03 03:08+0000\n"
"Last-Translator: Sergi Almacellas <pokoli@gmail.com>\n"
"Language-Team: ca <LL@li.org>\n"
@@ -16,7 +16,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.6\n"
+"Generated-By: Babel 1.3\n"
#: keystone/clean.py:23
#, python-format
@@ -38,63 +38,224 @@ msgstr ""
msgid "%(property_name)s is not a %(display_expected_type)s"
msgstr ""
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
#: keystone/test.py:117
#, python-format
msgid "Failed to checkout %s"
msgstr ""
-#: keystone/auth/controllers.py:72
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr ""
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr ""
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
#, python-format
msgid "Project is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:78 keystone/auth/plugins/password.py:39
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
#, python-format
msgid "Domain is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:84 keystone/auth/plugins/password.py:45
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
#, python-format
msgid "User is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:265
+#: keystone/auth/controllers.py:262
msgid "Scoping to both domain and project is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:268
+#: keystone/auth/controllers.py:265
msgid "Scoping to both domain and trust is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:271
+#: keystone/auth/controllers.py:268
msgid "Scoping to both project and trust is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:333
-#, fuzzy, python-format
-msgid "Unable to lookup user %s"
-msgstr "No es pot afegir el token a la llista d'usuaris."
-
-#: keystone/auth/controllers.py:363
+#: keystone/auth/controllers.py:353
msgid "User not found"
msgstr ""
-#: keystone/auth/token_factory.py:81
-msgid "User have no access to project"
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
msgstr ""
-#: keystone/auth/token_factory.py:96
-msgid "User have no access to domain"
-msgstr ""
-
-#: keystone/auth/token_factory.py:314 keystone/token/controllers.py:121
-#, fuzzy
-msgid "Unable to sign token."
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
+#, fuzzy, python-format
+msgid "Unable to lookup user %s"
msgstr "No es pot afegir el token a la llista d'usuaris."
-#: keystone/auth/token_factory.py:317 keystone/token/controllers.py:124
-#, python-format
-msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
msgstr ""
#: keystone/catalog/core.py:38
@@ -121,18 +282,18 @@ msgstr ""
msgid "Unable to open template file %s"
msgstr ""
-#: keystone/common/cms.py:42
+#: keystone/common/cms.py:26
#, python-format
msgid "Verify error: %s"
msgstr ""
-#: keystone/common/cms.py:134
+#: keystone/common/cms.py:118
msgid ""
"Signing error: Unable to load certificate - ensure you've configured PKI "
"with 'keystone-manage pki_setup'"
msgstr ""
-#: keystone/common/cms.py:138
+#: keystone/common/cms.py:122
#, python-format
msgid "Signing error: %s"
msgstr ""
@@ -151,31 +312,31 @@ msgstr "Fitxer syslog invàlid"
msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
msgstr ""
-#: keystone/common/controller.py:26
+#: keystone/common/controller.py:25
msgid "RBAC: Invalid token"
msgstr ""
-#: keystone/common/controller.py:36 keystone/common/controller.py:57
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
msgid "RBAC: Invalid user"
msgstr ""
-#: keystone/common/controller.py:42
+#: keystone/common/controller.py:45
msgid "RBAC: Proceeding without project"
msgstr ""
-#: keystone/common/controller.py:62
+#: keystone/common/controller.py:65
msgid "RBAC: Proceeding without tenant"
msgstr ""
-#: keystone/common/controller.py:92 keystone/common/controller.py:144
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
msgid "RBAC: Bypassing authorization"
msgstr ""
-#: keystone/common/controller.py:101 keystone/common/controller.py:142
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
msgid "RBAC: Authorization granted"
msgstr ""
-#: keystone/common/controller.py:131
+#: keystone/common/controller.py:134
#, python-format
msgid "RBAC: Adding query filter params (%s)"
msgstr ""
@@ -184,33 +345,69 @@ msgstr ""
msgid "Invalid token in normalize_domain_id"
msgstr ""
-#: keystone/common/utils.py:232
+#: keystone/common/utils.py:233
msgid ""
"Error setting up the debug environment. Verify that the option --debug-"
"url has the format <host>:<port> and that a debugger processes is "
"listening on that port."
msgstr ""
-#: keystone/common/wsgi.py:162
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
#, python-format
msgid "arg_dict: %s"
msgstr ""
-#: keystone/common/wsgi.py:186
+#: keystone/common/wsgi.py:243
#, python-format
msgid "Authorization failed. %(exception)s from %(remote_addr)s"
msgstr ""
-#: keystone/common/wsgi.py:429
+#: keystone/common/wsgi.py:487
msgid "The resource could not be found."
msgstr ""
-#: keystone/common/wsgi_server.py:72
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
#, python-format
msgid "Starting %(arg0)s on %(host)s:%(port)s"
msgstr ""
-#: keystone/common/wsgi_server.py:132
+#: keystone/common/environment/eventlet_server.py:113
msgid "Server error"
msgstr ""
@@ -243,13 +440,13 @@ msgid ""
"\"%(attr_map)s\" must use one of %(keys)s."
msgstr ""
-#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:596
-#: keystone/identity/backends/kvs.py:624
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
#, python-format
msgid "Duplicate name, %s."
msgstr ""
-#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:589
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
#, python-format
msgid "Duplicate ID, %s."
msgstr ""
@@ -437,12 +634,16 @@ msgstr ""
msgid "Search scope %s not implemented."
msgstr ""
-#: keystone/common/sql/core.py:205
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
#, python-format
msgid "Got mysql server has gone away: %s"
msgstr ""
-#: keystone/common/sql/legacy.py:180
+#: keystone/common/sql/legacy.py:188
#, python-format
msgid "Cannot migrate EC2 credential: %s"
msgstr ""
@@ -451,76 +652,68 @@ msgstr ""
msgid "version should be an integer"
msgstr ""
-#: keystone/common/sql/nova.py:62
+#: keystone/common/sql/nova.py:65
#, python-format
msgid "Create tenant %s"
msgstr ""
-#: keystone/common/sql/nova.py:79
+#: keystone/common/sql/nova.py:82
#, python-format
msgid "Create user %s"
msgstr ""
-#: keystone/common/sql/nova.py:88
+#: keystone/common/sql/nova.py:91
#, python-format
msgid "Add user %(user_id)s to tenant %(tenant_id)s"
msgstr ""
-#: keystone/common/sql/nova.py:97
+#: keystone/common/sql/nova.py:100
#, python-format
msgid "Ignoring existing role %s"
msgstr ""
-#: keystone/common/sql/nova.py:104
+#: keystone/common/sql/nova.py:107
#, python-format
msgid "Create role %s"
msgstr ""
-#: keystone/common/sql/nova.py:114
+#: keystone/common/sql/nova.py:117
#, python-format
msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
msgstr ""
-#: keystone/common/sql/nova.py:133
+#: keystone/common/sql/nova.py:136
#, python-format
msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
msgstr ""
-#: keystone/identity/backends/kvs.py:250 keystone/identity/backends/kvs.py:259
-msgid "User not found in group"
-msgstr ""
-
-#: keystone/identity/backends/sql.py:425
+#: keystone/identity/controllers.py:952
#, python-format
-msgid "Cannot remove role that has not been granted, %s"
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:82
-#, python-format
-msgid "Expected dict or list: %s"
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
+msgid "User not found in group"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:681
+#: keystone/identity/backends/ldap.py:189
#, python-format
-msgid "Role %s not found"
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
msgstr ""
-#: keystone/identity/backends/ldap/core.py:898
+#: keystone/identity/backends/ldap.py:334
msgid "Changing Name not supported by LDAP"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:911
+#: keystone/identity/backends/ldap.py:347
#, python-format
msgid "User %(user_id)s is already a member of group %(group_id)s"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:954
-#, python-format
-msgid ""
-"Group member '%(user_dn)s' not found in '%(group_dn)s'. The user should "
-"be removed from the group. The user will be ignored."
-msgstr ""
-
#: keystone/openstack/common/policy.py:394
#, python-format
msgid "Failed to understand rule %(rule)s"
@@ -536,21 +729,56 @@ msgstr ""
msgid "Failed to understand rule %(rule)r"
msgstr ""
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
#: keystone/policy/backends/rules.py:93
#, python-format
msgid "enforce %(action)s: %(credentials)s"
msgstr ""
-#: keystone/token/controllers.py:465 keystone/token/controllers.py:468
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
msgid "Token does not belong to specified tenant."
msgstr ""
-#: keystone/token/controllers.py:475
-msgid "Non-default domain is not supported"
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
msgstr ""
-#: keystone/token/controllers.py:483
-msgid "Domain scoped token is not supported"
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
msgstr ""
#: keystone/token/backends/memcache.py:144
@@ -575,3 +803,55 @@ msgstr ""
msgid "Unable to add token to revocation list."
msgstr "No es pot afegir el token a la llista de revocats."
+#: keystone/token/providers/pki.py:43
+#, fuzzy
+msgid "Unable to sign token."
+msgstr "No es pot afegir el token a la llista d'usuaris."
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
+#~ msgid "User have no access to project"
+#~ msgstr ""
+
+#~ msgid "User have no access to domain"
+#~ msgstr ""
+
+#~ msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+#~ msgstr ""
+
diff --git a/keystone/locale/cs/LC_MESSAGES/keystone.po b/keystone/locale/cs/LC_MESSAGES/keystone.po
index 104e202c..75cddd40 100644
--- a/keystone/locale/cs/LC_MESSAGES/keystone.po
+++ b/keystone/locale/cs/LC_MESSAGES/keystone.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Keystone\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2013-06-17 17:09+0000\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
"PO-Revision-Date: 2013-05-17 16:06+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
"Language-Team: Czech "
@@ -16,7 +16,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.6\n"
+"Generated-By: Babel 1.3\n"
#: keystone/clean.py:23
#, python-format
@@ -38,62 +38,224 @@ msgstr ""
msgid "%(property_name)s is not a %(display_expected_type)s"
msgstr ""
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
#: keystone/test.py:117
#, python-format
msgid "Failed to checkout %s"
msgstr ""
-#: keystone/auth/controllers.py:72
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr ""
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr ""
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
#, python-format
msgid "Project is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:78 keystone/auth/plugins/password.py:39
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
#, python-format
msgid "Domain is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:84 keystone/auth/plugins/password.py:45
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
#, python-format
msgid "User is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:265
+#: keystone/auth/controllers.py:262
msgid "Scoping to both domain and project is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:268
+#: keystone/auth/controllers.py:265
msgid "Scoping to both domain and trust is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:271
+#: keystone/auth/controllers.py:268
msgid "Scoping to both project and trust is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:333
-#, python-format
-msgid "Unable to lookup user %s"
-msgstr ""
-
-#: keystone/auth/controllers.py:363
+#: keystone/auth/controllers.py:353
msgid "User not found"
msgstr ""
-#: keystone/auth/token_factory.py:81
-msgid "User have no access to project"
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
msgstr ""
-#: keystone/auth/token_factory.py:96
-msgid "User have no access to domain"
-msgstr ""
-
-#: keystone/auth/token_factory.py:314 keystone/token/controllers.py:121
-msgid "Unable to sign token."
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
+#, python-format
+msgid "Unable to lookup user %s"
msgstr ""
-#: keystone/auth/token_factory.py:317 keystone/token/controllers.py:124
-#, python-format
-msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
msgstr ""
#: keystone/catalog/core.py:38
@@ -120,18 +282,18 @@ msgstr ""
msgid "Unable to open template file %s"
msgstr ""
-#: keystone/common/cms.py:42
+#: keystone/common/cms.py:26
#, python-format
msgid "Verify error: %s"
msgstr ""
-#: keystone/common/cms.py:134
+#: keystone/common/cms.py:118
msgid ""
"Signing error: Unable to load certificate - ensure you've configured PKI "
"with 'keystone-manage pki_setup'"
msgstr ""
-#: keystone/common/cms.py:138
+#: keystone/common/cms.py:122
#, python-format
msgid "Signing error: %s"
msgstr ""
@@ -150,31 +312,31 @@ msgstr ""
msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
msgstr ""
-#: keystone/common/controller.py:26
+#: keystone/common/controller.py:25
msgid "RBAC: Invalid token"
msgstr ""
-#: keystone/common/controller.py:36 keystone/common/controller.py:57
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
msgid "RBAC: Invalid user"
msgstr ""
-#: keystone/common/controller.py:42
+#: keystone/common/controller.py:45
msgid "RBAC: Proceeding without project"
msgstr ""
-#: keystone/common/controller.py:62
+#: keystone/common/controller.py:65
msgid "RBAC: Proceeding without tenant"
msgstr ""
-#: keystone/common/controller.py:92 keystone/common/controller.py:144
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
msgid "RBAC: Bypassing authorization"
msgstr ""
-#: keystone/common/controller.py:101 keystone/common/controller.py:142
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
msgid "RBAC: Authorization granted"
msgstr ""
-#: keystone/common/controller.py:131
+#: keystone/common/controller.py:134
#, python-format
msgid "RBAC: Adding query filter params (%s)"
msgstr ""
@@ -183,33 +345,69 @@ msgstr ""
msgid "Invalid token in normalize_domain_id"
msgstr ""
-#: keystone/common/utils.py:232
+#: keystone/common/utils.py:233
msgid ""
"Error setting up the debug environment. Verify that the option --debug-"
"url has the format <host>:<port> and that a debugger processes is "
"listening on that port."
msgstr ""
-#: keystone/common/wsgi.py:162
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
#, python-format
msgid "arg_dict: %s"
msgstr ""
-#: keystone/common/wsgi.py:186
+#: keystone/common/wsgi.py:243
#, python-format
msgid "Authorization failed. %(exception)s from %(remote_addr)s"
msgstr ""
-#: keystone/common/wsgi.py:429
+#: keystone/common/wsgi.py:487
msgid "The resource could not be found."
msgstr ""
-#: keystone/common/wsgi_server.py:72
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
#, python-format
msgid "Starting %(arg0)s on %(host)s:%(port)s"
msgstr ""
-#: keystone/common/wsgi_server.py:132
+#: keystone/common/environment/eventlet_server.py:113
msgid "Server error"
msgstr ""
@@ -242,13 +440,13 @@ msgid ""
"\"%(attr_map)s\" must use one of %(keys)s."
msgstr ""
-#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:596
-#: keystone/identity/backends/kvs.py:624
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
#, python-format
msgid "Duplicate name, %s."
msgstr ""
-#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:589
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
#, python-format
msgid "Duplicate ID, %s."
msgstr ""
@@ -436,12 +634,16 @@ msgstr ""
msgid "Search scope %s not implemented."
msgstr ""
-#: keystone/common/sql/core.py:205
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
#, python-format
msgid "Got mysql server has gone away: %s"
msgstr ""
-#: keystone/common/sql/legacy.py:180
+#: keystone/common/sql/legacy.py:188
#, python-format
msgid "Cannot migrate EC2 credential: %s"
msgstr ""
@@ -450,76 +652,68 @@ msgstr ""
msgid "version should be an integer"
msgstr ""
-#: keystone/common/sql/nova.py:62
+#: keystone/common/sql/nova.py:65
#, python-format
msgid "Create tenant %s"
msgstr ""
-#: keystone/common/sql/nova.py:79
+#: keystone/common/sql/nova.py:82
#, python-format
msgid "Create user %s"
msgstr ""
-#: keystone/common/sql/nova.py:88
+#: keystone/common/sql/nova.py:91
#, python-format
msgid "Add user %(user_id)s to tenant %(tenant_id)s"
msgstr ""
-#: keystone/common/sql/nova.py:97
+#: keystone/common/sql/nova.py:100
#, python-format
msgid "Ignoring existing role %s"
msgstr ""
-#: keystone/common/sql/nova.py:104
+#: keystone/common/sql/nova.py:107
#, python-format
msgid "Create role %s"
msgstr ""
-#: keystone/common/sql/nova.py:114
+#: keystone/common/sql/nova.py:117
#, python-format
msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
msgstr ""
-#: keystone/common/sql/nova.py:133
+#: keystone/common/sql/nova.py:136
#, python-format
msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
msgstr ""
-#: keystone/identity/backends/kvs.py:250 keystone/identity/backends/kvs.py:259
-msgid "User not found in group"
-msgstr ""
-
-#: keystone/identity/backends/sql.py:425
+#: keystone/identity/controllers.py:952
#, python-format
-msgid "Cannot remove role that has not been granted, %s"
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:82
-#, python-format
-msgid "Expected dict or list: %s"
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
+msgid "User not found in group"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:681
+#: keystone/identity/backends/ldap.py:189
#, python-format
-msgid "Role %s not found"
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
msgstr ""
-#: keystone/identity/backends/ldap/core.py:898
+#: keystone/identity/backends/ldap.py:334
msgid "Changing Name not supported by LDAP"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:911
+#: keystone/identity/backends/ldap.py:347
#, python-format
msgid "User %(user_id)s is already a member of group %(group_id)s"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:954
-#, python-format
-msgid ""
-"Group member '%(user_dn)s' not found in '%(group_dn)s'. The user should "
-"be removed from the group. The user will be ignored."
-msgstr ""
-
#: keystone/openstack/common/policy.py:394
#, python-format
msgid "Failed to understand rule %(rule)s"
@@ -535,21 +729,56 @@ msgstr ""
msgid "Failed to understand rule %(rule)r"
msgstr ""
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
#: keystone/policy/backends/rules.py:93
#, python-format
msgid "enforce %(action)s: %(credentials)s"
msgstr ""
-#: keystone/token/controllers.py:465 keystone/token/controllers.py:468
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
msgid "Token does not belong to specified tenant."
msgstr ""
-#: keystone/token/controllers.py:475
-msgid "Non-default domain is not supported"
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
msgstr ""
-#: keystone/token/controllers.py:483
-msgid "Domain scoped token is not supported"
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
msgstr ""
#: keystone/token/backends/memcache.py:144
@@ -574,3 +803,54 @@ msgstr ""
msgid "Unable to add token to revocation list."
msgstr ""
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
+#~ msgid "User have no access to project"
+#~ msgstr ""
+
+#~ msgid "User have no access to domain"
+#~ msgstr ""
+
+#~ msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+#~ msgstr ""
+
diff --git a/keystone/locale/da/LC_MESSAGES/keystone.po b/keystone/locale/da/LC_MESSAGES/keystone.po
index 83a0f31b..4243c60f 100644
--- a/keystone/locale/da/LC_MESSAGES/keystone.po
+++ b/keystone/locale/da/LC_MESSAGES/keystone.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Keystone\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2013-06-17 17:09+0000\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
"PO-Revision-Date: 2013-05-17 16:06+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
"Language-Team: Danish "
@@ -16,7 +16,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.6\n"
+"Generated-By: Babel 1.3\n"
#: keystone/clean.py:23
#, python-format
@@ -38,62 +38,224 @@ msgstr ""
msgid "%(property_name)s is not a %(display_expected_type)s"
msgstr ""
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
#: keystone/test.py:117
#, python-format
msgid "Failed to checkout %s"
msgstr ""
-#: keystone/auth/controllers.py:72
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr ""
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr ""
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
#, python-format
msgid "Project is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:78 keystone/auth/plugins/password.py:39
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
#, python-format
msgid "Domain is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:84 keystone/auth/plugins/password.py:45
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
#, python-format
msgid "User is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:265
+#: keystone/auth/controllers.py:262
msgid "Scoping to both domain and project is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:268
+#: keystone/auth/controllers.py:265
msgid "Scoping to both domain and trust is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:271
+#: keystone/auth/controllers.py:268
msgid "Scoping to both project and trust is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:333
-#, python-format
-msgid "Unable to lookup user %s"
-msgstr ""
-
-#: keystone/auth/controllers.py:363
+#: keystone/auth/controllers.py:353
msgid "User not found"
msgstr ""
-#: keystone/auth/token_factory.py:81
-msgid "User have no access to project"
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
msgstr ""
-#: keystone/auth/token_factory.py:96
-msgid "User have no access to domain"
-msgstr ""
-
-#: keystone/auth/token_factory.py:314 keystone/token/controllers.py:121
-msgid "Unable to sign token."
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
+#, python-format
+msgid "Unable to lookup user %s"
msgstr ""
-#: keystone/auth/token_factory.py:317 keystone/token/controllers.py:124
-#, python-format
-msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
msgstr ""
#: keystone/catalog/core.py:38
@@ -120,18 +282,18 @@ msgstr ""
msgid "Unable to open template file %s"
msgstr ""
-#: keystone/common/cms.py:42
+#: keystone/common/cms.py:26
#, python-format
msgid "Verify error: %s"
msgstr ""
-#: keystone/common/cms.py:134
+#: keystone/common/cms.py:118
msgid ""
"Signing error: Unable to load certificate - ensure you've configured PKI "
"with 'keystone-manage pki_setup'"
msgstr ""
-#: keystone/common/cms.py:138
+#: keystone/common/cms.py:122
#, python-format
msgid "Signing error: %s"
msgstr ""
@@ -150,31 +312,31 @@ msgstr ""
msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
msgstr ""
-#: keystone/common/controller.py:26
+#: keystone/common/controller.py:25
msgid "RBAC: Invalid token"
msgstr ""
-#: keystone/common/controller.py:36 keystone/common/controller.py:57
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
msgid "RBAC: Invalid user"
msgstr ""
-#: keystone/common/controller.py:42
+#: keystone/common/controller.py:45
msgid "RBAC: Proceeding without project"
msgstr ""
-#: keystone/common/controller.py:62
+#: keystone/common/controller.py:65
msgid "RBAC: Proceeding without tenant"
msgstr ""
-#: keystone/common/controller.py:92 keystone/common/controller.py:144
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
msgid "RBAC: Bypassing authorization"
msgstr ""
-#: keystone/common/controller.py:101 keystone/common/controller.py:142
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
msgid "RBAC: Authorization granted"
msgstr ""
-#: keystone/common/controller.py:131
+#: keystone/common/controller.py:134
#, python-format
msgid "RBAC: Adding query filter params (%s)"
msgstr ""
@@ -183,33 +345,69 @@ msgstr ""
msgid "Invalid token in normalize_domain_id"
msgstr ""
-#: keystone/common/utils.py:232
+#: keystone/common/utils.py:233
msgid ""
"Error setting up the debug environment. Verify that the option --debug-"
"url has the format <host>:<port> and that a debugger processes is "
"listening on that port."
msgstr ""
-#: keystone/common/wsgi.py:162
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
#, python-format
msgid "arg_dict: %s"
msgstr ""
-#: keystone/common/wsgi.py:186
+#: keystone/common/wsgi.py:243
#, python-format
msgid "Authorization failed. %(exception)s from %(remote_addr)s"
msgstr ""
-#: keystone/common/wsgi.py:429
+#: keystone/common/wsgi.py:487
msgid "The resource could not be found."
msgstr ""
-#: keystone/common/wsgi_server.py:72
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
#, python-format
msgid "Starting %(arg0)s on %(host)s:%(port)s"
msgstr ""
-#: keystone/common/wsgi_server.py:132
+#: keystone/common/environment/eventlet_server.py:113
msgid "Server error"
msgstr ""
@@ -242,13 +440,13 @@ msgid ""
"\"%(attr_map)s\" must use one of %(keys)s."
msgstr ""
-#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:596
-#: keystone/identity/backends/kvs.py:624
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
#, python-format
msgid "Duplicate name, %s."
msgstr ""
-#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:589
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
#, python-format
msgid "Duplicate ID, %s."
msgstr ""
@@ -436,12 +634,16 @@ msgstr ""
msgid "Search scope %s not implemented."
msgstr ""
-#: keystone/common/sql/core.py:205
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
#, python-format
msgid "Got mysql server has gone away: %s"
msgstr ""
-#: keystone/common/sql/legacy.py:180
+#: keystone/common/sql/legacy.py:188
#, python-format
msgid "Cannot migrate EC2 credential: %s"
msgstr ""
@@ -450,76 +652,68 @@ msgstr ""
msgid "version should be an integer"
msgstr ""
-#: keystone/common/sql/nova.py:62
+#: keystone/common/sql/nova.py:65
#, python-format
msgid "Create tenant %s"
msgstr ""
-#: keystone/common/sql/nova.py:79
+#: keystone/common/sql/nova.py:82
#, python-format
msgid "Create user %s"
msgstr ""
-#: keystone/common/sql/nova.py:88
+#: keystone/common/sql/nova.py:91
#, python-format
msgid "Add user %(user_id)s to tenant %(tenant_id)s"
msgstr ""
-#: keystone/common/sql/nova.py:97
+#: keystone/common/sql/nova.py:100
#, python-format
msgid "Ignoring existing role %s"
msgstr ""
-#: keystone/common/sql/nova.py:104
+#: keystone/common/sql/nova.py:107
#, python-format
msgid "Create role %s"
msgstr ""
-#: keystone/common/sql/nova.py:114
+#: keystone/common/sql/nova.py:117
#, python-format
msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
msgstr ""
-#: keystone/common/sql/nova.py:133
+#: keystone/common/sql/nova.py:136
#, python-format
msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
msgstr ""
-#: keystone/identity/backends/kvs.py:250 keystone/identity/backends/kvs.py:259
-msgid "User not found in group"
-msgstr ""
-
-#: keystone/identity/backends/sql.py:425
+#: keystone/identity/controllers.py:952
#, python-format
-msgid "Cannot remove role that has not been granted, %s"
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:82
-#, python-format
-msgid "Expected dict or list: %s"
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
+msgid "User not found in group"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:681
+#: keystone/identity/backends/ldap.py:189
#, python-format
-msgid "Role %s not found"
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
msgstr ""
-#: keystone/identity/backends/ldap/core.py:898
+#: keystone/identity/backends/ldap.py:334
msgid "Changing Name not supported by LDAP"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:911
+#: keystone/identity/backends/ldap.py:347
#, python-format
msgid "User %(user_id)s is already a member of group %(group_id)s"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:954
-#, python-format
-msgid ""
-"Group member '%(user_dn)s' not found in '%(group_dn)s'. The user should "
-"be removed from the group. The user will be ignored."
-msgstr ""
-
#: keystone/openstack/common/policy.py:394
#, python-format
msgid "Failed to understand rule %(rule)s"
@@ -535,21 +729,56 @@ msgstr ""
msgid "Failed to understand rule %(rule)r"
msgstr ""
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
#: keystone/policy/backends/rules.py:93
#, python-format
msgid "enforce %(action)s: %(credentials)s"
msgstr ""
-#: keystone/token/controllers.py:465 keystone/token/controllers.py:468
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
msgid "Token does not belong to specified tenant."
msgstr ""
-#: keystone/token/controllers.py:475
-msgid "Non-default domain is not supported"
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
msgstr ""
-#: keystone/token/controllers.py:483
-msgid "Domain scoped token is not supported"
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
msgstr ""
#: keystone/token/backends/memcache.py:144
@@ -574,3 +803,54 @@ msgstr ""
msgid "Unable to add token to revocation list."
msgstr ""
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
+#~ msgid "User have no access to project"
+#~ msgstr ""
+
+#~ msgid "User have no access to domain"
+#~ msgstr ""
+
+#~ msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+#~ msgstr ""
+
diff --git a/keystone/locale/de/LC_MESSAGES/keystone.po b/keystone/locale/de/LC_MESSAGES/keystone.po
index 4d38a328..eb3b905d 100644
--- a/keystone/locale/de/LC_MESSAGES/keystone.po
+++ b/keystone/locale/de/LC_MESSAGES/keystone.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Keystone\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2013-06-17 17:09+0000\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
"PO-Revision-Date: 2013-05-22 03:45+0000\n"
"Last-Translator: daisy.ycguo <daisy.ycguo@gmail.com>\n"
"Language-Team: German "
@@ -16,7 +16,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.6\n"
+"Generated-By: Babel 1.3\n"
#: keystone/clean.py:23
#, python-format
@@ -38,65 +38,225 @@ msgstr "%(property_name)s sollte nicht größer als %(max_length)s Zeichen sein.
msgid "%(property_name)s is not a %(display_expected_type)s"
msgstr ""
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
#: keystone/test.py:117
#, python-format
msgid "Failed to checkout %s"
msgstr "%s wurde nicht ausgecheckt"
-#: keystone/auth/controllers.py:72
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr "Nicht gewährte Rolle kann nicht entfernt werden, %s"
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr "Rolle %s nicht gefunden"
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
#, python-format
msgid "Project is disabled: %s"
msgstr "Projekt ist inaktiviert: %s"
-#: keystone/auth/controllers.py:78 keystone/auth/plugins/password.py:39
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
#, python-format
msgid "Domain is disabled: %s"
msgstr "Domäne ist inaktiviert: %s"
-#: keystone/auth/controllers.py:84 keystone/auth/plugins/password.py:45
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
#, python-format
msgid "User is disabled: %s"
msgstr "Benutzer ist inaktiviert: %s"
-#: keystone/auth/controllers.py:265
+#: keystone/auth/controllers.py:262
msgid "Scoping to both domain and project is not allowed"
msgstr "Scoping sowohl auf 'domain' als auch auf 'project' ist nicht zulässig"
-#: keystone/auth/controllers.py:268
+#: keystone/auth/controllers.py:265
msgid "Scoping to both domain and trust is not allowed"
msgstr "Scoping sowohl auf 'domain' als auch auf 'trust' ist nicht zulässig"
-#: keystone/auth/controllers.py:271
+#: keystone/auth/controllers.py:268
msgid "Scoping to both project and trust is not allowed"
msgstr "Scoping sowohl auf 'project' als auch auf 'trust' ist nicht zulässig"
-#: keystone/auth/controllers.py:333
-#, python-format
-msgid "Unable to lookup user %s"
-msgstr "Suche nach Benutzer %s nicht möglich"
-
-#: keystone/auth/controllers.py:363
+#: keystone/auth/controllers.py:353
msgid "User not found"
msgstr "Benutzer nicht gefunden"
-#: keystone/auth/token_factory.py:81
-msgid "User have no access to project"
-msgstr "Benutzer hat keinen Zugriff auf Projekt"
-
-#: keystone/auth/token_factory.py:96
-msgid "User have no access to domain"
-msgstr "Benutzer hat keinen Zugriff auf Domäne"
-
-#: keystone/auth/token_factory.py:314 keystone/token/controllers.py:121
-msgid "Unable to sign token."
-msgstr "Token kann nicht unterzeichnet werden."
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
+msgstr ""
-#: keystone/auth/token_factory.py:317 keystone/token/controllers.py:124
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
#, python-format
-msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+msgid "Unable to lookup user %s"
+msgstr "Suche nach Benutzer %s nicht möglich"
+
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
msgstr ""
-"Ungültiger Wert für 'token_format': %s. Zulässige Werte sind PKI oder "
-"UUID."
#: keystone/catalog/core.py:38
#, python-format
@@ -126,12 +286,12 @@ msgstr ""
msgid "Unable to open template file %s"
msgstr "Vorlagendatei %s kann nicht geöffnet werden"
-#: keystone/common/cms.py:42
+#: keystone/common/cms.py:26
#, python-format
msgid "Verify error: %s"
msgstr "Fehler überprüfen: %s"
-#: keystone/common/cms.py:134
+#: keystone/common/cms.py:118
msgid ""
"Signing error: Unable to load certificate - ensure you've configured PKI "
"with 'keystone-manage pki_setup'"
@@ -139,7 +299,7 @@ msgstr ""
"Unterzeichnungsfehler: Zertifikat kann nicht geladen werden - stellen Sie"
" sicher, dass Sie PKI mit 'keystone-manage pki_setup' konfiguriert haben"
-#: keystone/common/cms.py:138
+#: keystone/common/cms.py:122
#, python-format
msgid "Signing error: %s"
msgstr "Unterzeichnungsfehler: %s"
@@ -158,31 +318,31 @@ msgstr "Ungültige 'syslog'-Funktion"
msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
msgstr ""
-#: keystone/common/controller.py:26
+#: keystone/common/controller.py:25
msgid "RBAC: Invalid token"
msgstr "Rollenbasierte Zugriffssteuerung: Ungültiges Token"
-#: keystone/common/controller.py:36 keystone/common/controller.py:57
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
msgid "RBAC: Invalid user"
msgstr "Rollenbasierte Zugriffssteuerung: Ungültiger Benutzer"
-#: keystone/common/controller.py:42
+#: keystone/common/controller.py:45
msgid "RBAC: Proceeding without project"
msgstr "Rollenbasierte Zugriffssteuerung: Fortfahren ohne Projekt"
-#: keystone/common/controller.py:62
+#: keystone/common/controller.py:65
msgid "RBAC: Proceeding without tenant"
msgstr "Rollenbasierte Zugriffssteuerung: Fortsetzung ohne Nutzer"
-#: keystone/common/controller.py:92 keystone/common/controller.py:144
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
msgid "RBAC: Bypassing authorization"
msgstr "Rollenbasierte Zugriffssteuerung: Umgehen von Autorisierung"
-#: keystone/common/controller.py:101 keystone/common/controller.py:142
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
msgid "RBAC: Authorization granted"
msgstr "Rollenbasierte Zugriffssteuerung: Autorisierung erteilt"
-#: keystone/common/controller.py:131
+#: keystone/common/controller.py:134
#, python-format
msgid "RBAC: Adding query filter params (%s)"
msgstr ""
@@ -193,33 +353,69 @@ msgstr ""
msgid "Invalid token in normalize_domain_id"
msgstr "Ungültiges Token in 'normalize_domain_id'"
-#: keystone/common/utils.py:232
+#: keystone/common/utils.py:233
msgid ""
"Error setting up the debug environment. Verify that the option --debug-"
"url has the format <host>:<port> and that a debugger processes is "
"listening on that port."
msgstr ""
-#: keystone/common/wsgi.py:162
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
#, python-format
msgid "arg_dict: %s"
msgstr "arg_dict: %s"
-#: keystone/common/wsgi.py:186
+#: keystone/common/wsgi.py:243
#, fuzzy, python-format
msgid "Authorization failed. %(exception)s from %(remote_addr)s"
msgstr "Autorisierung fehlgeschlagen. %s von %s"
-#: keystone/common/wsgi.py:429
+#: keystone/common/wsgi.py:487
msgid "The resource could not be found."
msgstr "Die Ressource konnte nicht gefunden werden."
-#: keystone/common/wsgi_server.py:72
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
#, python-format
msgid "Starting %(arg0)s on %(host)s:%(port)s"
msgstr "Starten von %(arg0)s auf %(host)s:%(port)s"
-#: keystone/common/wsgi_server.py:132
+#: keystone/common/environment/eventlet_server.py:113
msgid "Server error"
msgstr "Serverfehler"
@@ -252,13 +448,13 @@ msgid ""
"\"%(attr_map)s\" must use one of %(keys)s."
msgstr ""
-#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:596
-#: keystone/identity/backends/kvs.py:624
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
#, python-format
msgid "Duplicate name, %s."
msgstr "Doppelter Name, %s."
-#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:589
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
#, python-format
msgid "Duplicate ID, %s."
msgstr "Doppelte ID, %s."
@@ -452,14 +648,18 @@ msgstr "FakeLdap-Suche fehlgeschlagen: dn für 'SCOPE_BASE' nicht gefunden"
msgid "Search scope %s not implemented."
msgstr "Suchbereich %s nicht implementiert."
-#: keystone/common/sql/core.py:205
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
#, python-format
msgid "Got mysql server has gone away: %s"
msgstr ""
"Es wurde festgestellt, dass keine Verbindung zum mysql-Server mehr "
"vorhanden ist: %s"
-#: keystone/common/sql/legacy.py:180
+#: keystone/common/sql/legacy.py:188
#, python-format
msgid "Cannot migrate EC2 credential: %s"
msgstr "EC2-Berechtigungsnachweis kann nicht migriert werden: %s"
@@ -468,76 +668,68 @@ msgstr "EC2-Berechtigungsnachweis kann nicht migriert werden: %s"
msgid "version should be an integer"
msgstr "Version sollte eine Ganzzahl sein"
-#: keystone/common/sql/nova.py:62
+#: keystone/common/sql/nova.py:65
#, python-format
msgid "Create tenant %s"
msgstr "Nutzer %s erstellen"
-#: keystone/common/sql/nova.py:79
+#: keystone/common/sql/nova.py:82
#, python-format
msgid "Create user %s"
msgstr "Benutzer %s erstellen"
-#: keystone/common/sql/nova.py:88
+#: keystone/common/sql/nova.py:91
#, fuzzy, python-format
msgid "Add user %(user_id)s to tenant %(tenant_id)s"
msgstr "Benutzer %s zu Nutzer %s hinzufügen"
-#: keystone/common/sql/nova.py:97
+#: keystone/common/sql/nova.py:100
#, python-format
msgid "Ignoring existing role %s"
msgstr "Vorhandene Rolle %s ignorieren"
-#: keystone/common/sql/nova.py:104
+#: keystone/common/sql/nova.py:107
#, python-format
msgid "Create role %s"
msgstr "Rolle %s erstellen"
-#: keystone/common/sql/nova.py:114
+#: keystone/common/sql/nova.py:117
#, fuzzy, python-format
msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
msgstr "Rolle %s Benutzer %s auf Nutzer %s zuweisen"
-#: keystone/common/sql/nova.py:133
+#: keystone/common/sql/nova.py:136
#, fuzzy, python-format
msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
msgstr "Erstellen von EC2-Berechtigungsnachweis für Benutzer %s und Nutzer %s"
-#: keystone/identity/backends/kvs.py:250 keystone/identity/backends/kvs.py:259
+#: keystone/identity/controllers.py:952
+#, python-format
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
+msgstr ""
+
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
msgid "User not found in group"
msgstr "Benutzer nicht in Gruppe gefunden"
-#: keystone/identity/backends/sql.py:425
-#, python-format
-msgid "Cannot remove role that has not been granted, %s"
-msgstr "Nicht gewährte Rolle kann nicht entfernt werden, %s"
-
-#: keystone/identity/backends/ldap/core.py:82
+#: keystone/identity/backends/ldap.py:189
#, python-format
-msgid "Expected dict or list: %s"
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
msgstr ""
-#: keystone/identity/backends/ldap/core.py:681
-#, python-format
-msgid "Role %s not found"
-msgstr "Rolle %s nicht gefunden"
-
-#: keystone/identity/backends/ldap/core.py:898
+#: keystone/identity/backends/ldap.py:334
msgid "Changing Name not supported by LDAP"
msgstr "Änderung von Namen wird von LDAP nicht unterstützt"
-#: keystone/identity/backends/ldap/core.py:911
+#: keystone/identity/backends/ldap.py:347
#, fuzzy, python-format
msgid "User %(user_id)s is already a member of group %(group_id)s"
msgstr "Benutzer %s ist bereits Mitglied der Gruppe %s."
-#: keystone/identity/backends/ldap/core.py:954
-#, python-format
-msgid ""
-"Group member '%(user_dn)s' not found in '%(group_dn)s'. The user should "
-"be removed from the group. The user will be ignored."
-msgstr ""
-
#: keystone/openstack/common/policy.py:394
#, python-format
msgid "Failed to understand rule %(rule)s"
@@ -553,22 +745,57 @@ msgstr "Kein Handler für Übereinstimmungen des Typs %s"
msgid "Failed to understand rule %(rule)r"
msgstr "Regel '%(rule)r' konnte nicht verstanden werden"
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
#: keystone/policy/backends/rules.py:93
#, python-format
msgid "enforce %(action)s: %(credentials)s"
msgstr ""
-#: keystone/token/controllers.py:465 keystone/token/controllers.py:468
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
msgid "Token does not belong to specified tenant."
msgstr "Token gehört nicht zu angegebenem Nutzer."
-#: keystone/token/controllers.py:475
-msgid "Non-default domain is not supported"
-msgstr "Nicht-Standard-Domäne wird nicht unterstützt"
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
+msgstr ""
-#: keystone/token/controllers.py:483
-msgid "Domain scoped token is not supported"
-msgstr "Bereichsorientiertes Token der Domäne wird nicht unterstützt"
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
+msgstr ""
#: keystone/token/backends/memcache.py:144
#, python-format
@@ -592,3 +819,56 @@ msgstr ""
msgid "Unable to add token to revocation list."
msgstr "Token kann nicht zu Widerrufsliste hinzugefügt werden."
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr "Token kann nicht unterzeichnet werden."
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr "Nicht-Standard-Domäne wird nicht unterstützt"
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr "Bereichsorientiertes Token der Domäne wird nicht unterstützt"
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
+#~ msgid "User have no access to project"
+#~ msgstr "Benutzer hat keinen Zugriff auf Projekt"
+
+#~ msgid "User have no access to domain"
+#~ msgstr "Benutzer hat keinen Zugriff auf Domäne"
+
+#~ msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+#~ msgstr ""
+#~ "Ungültiger Wert für 'token_format': %s. "
+#~ "Zulässige Werte sind PKI oder UUID."
+
diff --git a/keystone/locale/en_AU/LC_MESSAGES/keystone.po b/keystone/locale/en_AU/LC_MESSAGES/keystone.po
new file mode 100644
index 00000000..65c1161c
--- /dev/null
+++ b/keystone/locale/en_AU/LC_MESSAGES/keystone.po
@@ -0,0 +1,847 @@
+# English (Australia) translations for keystone.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the keystone project.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: Keystone\n"
+"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
+"PO-Revision-Date: 2013-07-29 22:01+0000\n"
+"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
+"Language-Team: English (Australia) "
+"(http://www.transifex.com/projects/p/openstack/language/en_AU/)\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: keystone/clean.py:23
+#, python-format
+msgid "%s cannot be empty."
+msgstr ""
+
+#: keystone/clean.py:25
+#, python-format
+msgid "%(property_name)s cannot be less than %(min_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:29
+#, python-format
+msgid "%(property_name)s should not be greater than %(max_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:36
+#, python-format
+msgid "%(property_name)s is not a %(display_expected_type)s"
+msgstr ""
+
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
+#: keystone/test.py:117
+#, python-format
+msgid "Failed to checkout %s"
+msgstr ""
+
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr ""
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr ""
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
+#, python-format
+msgid "Project is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
+#, python-format
+msgid "Domain is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
+#, python-format
+msgid "User is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:262
+msgid "Scoping to both domain and project is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:265
+msgid "Scoping to both domain and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:268
+msgid "Scoping to both project and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:353
+msgid "User not found"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
+#, python-format
+msgid "Unable to lookup user %s"
+msgstr ""
+
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
+msgstr ""
+
+#: keystone/catalog/core.py:38
+#, python-format
+msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s"
+msgstr ""
+
+#: keystone/catalog/core.py:43
+#, python-format
+msgid ""
+"Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing "
+"brackets ?)"
+msgstr ""
+
+#: keystone/catalog/core.py:49
+#, python-format
+msgid ""
+"Malformed endpoint %s - incomplete format (are you "
+"missing a type notifier ?)"
+msgstr ""
+
+#: keystone/catalog/backends/templated.py:109
+#, python-format
+msgid "Unable to open template file %s"
+msgstr ""
+
+#: keystone/common/cms.py:26
+#, python-format
+msgid "Verify error: %s"
+msgstr ""
+
+#: keystone/common/cms.py:118
+msgid ""
+"Signing error: Unable to load certificate - ensure you've configured PKI "
+"with 'keystone-manage pki_setup'"
+msgstr ""
+
+#: keystone/common/cms.py:122
+#, python-format
+msgid "Signing error: %s"
+msgstr ""
+
+#: keystone/common/config.py:89
+#, python-format
+msgid "Unable to locate specified logging config file: %s"
+msgstr ""
+
+#: keystone/common/config.py:107
+msgid "Invalid syslog facility"
+msgstr ""
+
+#: keystone/common/controller.py:18
+#, python-format
+msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
+msgstr ""
+
+#: keystone/common/controller.py:25
+msgid "RBAC: Invalid token"
+msgstr ""
+
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
+msgid "RBAC: Invalid user"
+msgstr ""
+
+#: keystone/common/controller.py:45
+msgid "RBAC: Proceeding without project"
+msgstr ""
+
+#: keystone/common/controller.py:65
+msgid "RBAC: Proceeding without tenant"
+msgstr ""
+
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
+msgid "RBAC: Bypassing authorization"
+msgstr ""
+
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
+msgid "RBAC: Authorization granted"
+msgstr ""
+
+#: keystone/common/controller.py:134
+#, python-format
+msgid "RBAC: Adding query filter params (%s)"
+msgstr ""
+
+#: keystone/common/controller.py:322
+msgid "Invalid token in normalize_domain_id"
+msgstr ""
+
+#: keystone/common/utils.py:233
+msgid ""
+"Error setting up the debug environment. Verify that the option --debug-"
+"url has the format <host>:<port> and that a debugger processes is "
+"listening on that port."
+msgstr ""
+
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
+#, python-format
+msgid "arg_dict: %s"
+msgstr ""
+
+#: keystone/common/wsgi.py:243
+#, python-format
+msgid "Authorization failed. %(exception)s from %(remote_addr)s"
+msgstr ""
+
+#: keystone/common/wsgi.py:487
+msgid "The resource could not be found."
+msgstr ""
+
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
+#, python-format
+msgid "Starting %(arg0)s on %(host)s:%(port)s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:113
+msgid "Server error"
+msgstr ""
+
+#: keystone/common/ldap/core.py:79
+#, python-format
+msgid "Invalid LDAP deref option: %s. Choose one of: "
+msgstr ""
+
+#: keystone/common/ldap/core.py:87
+#, python-format
+msgid "Invalid LDAP TLS certs option: %(option). Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:99
+#, python-format
+msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:189
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%s\". Format must be "
+"<ldap_attribute>:<keystone_attribute>"
+msgstr ""
+
+#: keystone/common/ldap/core.py:195
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%(item)s\". Value "
+"\"%(attr_map)s\" must use one of %(keys)s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
+#, python-format
+msgid "Duplicate name, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
+#, python-format
+msgid "Duplicate ID, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:294
+#, python-format
+msgid "LDAP %s create"
+msgstr ""
+
+#: keystone/common/ldap/core.py:372
+#, python-format
+msgid "LDAP %s update"
+msgstr ""
+
+#: keystone/common/ldap/core.py:405
+#, python-format
+msgid "LDAP %s delete"
+msgstr ""
+
+#: keystone/common/ldap/core.py:430
+#, python-format
+msgid "LDAP init: url=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:431
+#, python-format
+msgid ""
+"LDAP init: use_tls=%(use_tls)s\n"
+"tls_cacertfile=%(tls_cacertfile)s\n"
+"tls_cacertdir=%(tls_cacertdir)s\n"
+"tls_req_cert=%(tls_req_cert)s\n"
+"tls_avail=%(tls_avail)s\n"
+msgstr ""
+
+#: keystone/common/ldap/core.py:450
+msgid "Invalid TLS / LDAPS combination"
+msgstr ""
+
+#: keystone/common/ldap/core.py:454
+#, python-format
+msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available"
+msgstr ""
+
+#: keystone/common/ldap/core.py:464
+#, python-format
+msgid "tls_cacertfile %s not found or is not a file"
+msgstr ""
+
+#: keystone/common/ldap/core.py:476
+#, python-format
+msgid "tls_cacertdir %s not found or is not a directory"
+msgstr ""
+
+#: keystone/common/ldap/core.py:483
+#, python-format
+msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:497
+#, python-format
+msgid "LDAP bind: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:508
+#, python-format
+msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:514
+#, python-format
+msgid ""
+"LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, "
+"attrs=%(attrlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:567
+msgid ""
+"LDAP Server does not support paging. Disable paging in keystone.conf to "
+"avoid this message."
+msgstr ""
+
+#: keystone/common/ldap/core.py:584
+#, python-format
+msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:590
+#, python-format
+msgid "LDAP delete: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:595
+#, python-format
+msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:146
+#, python-format
+msgid "FakeLdap initialize url=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:156
+#, python-format
+msgid "FakeLdap bind dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:163
+#, python-format
+msgid "FakeLdap bind fail: dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:170
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:175
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s does not match"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:190
+#, python-format
+msgid "FakeLdap add item: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:193
+#, python-format
+msgid "FakeLdap add item failed: dn=%s is already in store."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:207 keystone/common/ldap/fakeldap.py:221
+#, python-format
+msgid "FakeLdap delete item: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:211 keystone/common/ldap/fakeldap.py:225
+#, python-format
+msgid "FakeLdap delete item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:240
+#, python-format
+msgid "FakeLdap modify item: dn=%(dn)s attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:245
+#, python-format
+msgid "FakeLdap modify item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:262
+#, python-format
+msgid "FakeLdap modify item failed: item has no attribute \"%s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:273
+#, python-format
+msgid ""
+"FakeLdap modify item failed: item has no attribute \"%(k)s\" with value "
+"\"%(v)s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:279
+#, python-format
+msgid "FakeLdap modify item failed: unknown command %s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:281
+#, python-format
+msgid "modify_s action %s not implemented"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:300
+#, python-format
+msgid "FakeLdap search at dn=%(dn)s scope=%(scope)s query=%(query)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:306
+msgid "FakeLdap search fail: dn not found for SCOPE_BASE"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:320
+#, python-format
+msgid "Search scope %s not implemented."
+msgstr ""
+
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
+#, python-format
+msgid "Got mysql server has gone away: %s"
+msgstr ""
+
+#: keystone/common/sql/legacy.py:188
+#, python-format
+msgid "Cannot migrate EC2 credential: %s"
+msgstr ""
+
+#: keystone/common/sql/migration.py:47
+msgid "version should be an integer"
+msgstr ""
+
+#: keystone/common/sql/nova.py:65
+#, python-format
+msgid "Create tenant %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:82
+#, python-format
+msgid "Create user %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:91
+#, python-format
+msgid "Add user %(user_id)s to tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:100
+#, python-format
+msgid "Ignoring existing role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:107
+#, python-format
+msgid "Create role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:117
+#, python-format
+msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:136
+#, python-format
+msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/identity/controllers.py:952
+#, python-format
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
+msgstr ""
+
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
+msgid "User not found in group"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:189
+#, python-format
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:334
+msgid "Changing Name not supported by LDAP"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:347
+#, python-format
+msgid "User %(user_id)s is already a member of group %(group_id)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:394
+#, python-format
+msgid "Failed to understand rule %(rule)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:404
+#, python-format
+msgid "No handler for matches of kind %s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:679
+#, python-format
+msgid "Failed to understand rule %(rule)r"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
+#: keystone/policy/backends/rules.py:93
+#, python-format
+msgid "enforce %(action)s: %(credentials)s"
+msgstr ""
+
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
+msgid "Token does not belong to specified tenant."
+msgstr ""
+
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
+msgstr ""
+
+#: keystone/token/backends/memcache.py:144
+#, python-format
+msgid ""
+"Successful set of token-index-list for user-key \"%(user_key)s\", "
+"#%(count)d records"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:154
+#, python-format
+msgid ""
+"Failed to set token-index-list for user-key \"%(user_key)s\". Attempt "
+"%(cas_retry)d of %(cas_retry_max)d"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:163
+msgid "Unable to add token user list"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:172
+msgid "Unable to add token to revocation list."
+msgstr ""
+
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
diff --git a/keystone/locale/en_GB/LC_MESSAGES/keystone.po b/keystone/locale/en_GB/LC_MESSAGES/keystone.po
new file mode 100644
index 00000000..73b4dbef
--- /dev/null
+++ b/keystone/locale/en_GB/LC_MESSAGES/keystone.po
@@ -0,0 +1,847 @@
+# English (United Kingdom) translations for keystone.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the keystone project.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: Keystone\n"
+"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
+"PO-Revision-Date: 2013-07-29 22:01+0000\n"
+"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
+"Language-Team: English (United Kingdom) "
+"(http://www.transifex.com/projects/p/openstack/language/en_GB/)\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: keystone/clean.py:23
+#, python-format
+msgid "%s cannot be empty."
+msgstr ""
+
+#: keystone/clean.py:25
+#, python-format
+msgid "%(property_name)s cannot be less than %(min_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:29
+#, python-format
+msgid "%(property_name)s should not be greater than %(max_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:36
+#, python-format
+msgid "%(property_name)s is not a %(display_expected_type)s"
+msgstr ""
+
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
+#: keystone/test.py:117
+#, python-format
+msgid "Failed to checkout %s"
+msgstr ""
+
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr ""
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr ""
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
+#, python-format
+msgid "Project is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
+#, python-format
+msgid "Domain is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
+#, python-format
+msgid "User is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:262
+msgid "Scoping to both domain and project is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:265
+msgid "Scoping to both domain and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:268
+msgid "Scoping to both project and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:353
+msgid "User not found"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
+#, python-format
+msgid "Unable to lookup user %s"
+msgstr ""
+
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
+msgstr ""
+
+#: keystone/catalog/core.py:38
+#, python-format
+msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s"
+msgstr ""
+
+#: keystone/catalog/core.py:43
+#, python-format
+msgid ""
+"Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing "
+"brackets ?)"
+msgstr ""
+
+#: keystone/catalog/core.py:49
+#, python-format
+msgid ""
+"Malformed endpoint %s - incomplete format (are you "
+"missing a type notifier ?)"
+msgstr ""
+
+#: keystone/catalog/backends/templated.py:109
+#, python-format
+msgid "Unable to open template file %s"
+msgstr ""
+
+#: keystone/common/cms.py:26
+#, python-format
+msgid "Verify error: %s"
+msgstr ""
+
+#: keystone/common/cms.py:118
+msgid ""
+"Signing error: Unable to load certificate - ensure you've configured PKI "
+"with 'keystone-manage pki_setup'"
+msgstr ""
+
+#: keystone/common/cms.py:122
+#, python-format
+msgid "Signing error: %s"
+msgstr ""
+
+#: keystone/common/config.py:89
+#, python-format
+msgid "Unable to locate specified logging config file: %s"
+msgstr ""
+
+#: keystone/common/config.py:107
+msgid "Invalid syslog facility"
+msgstr ""
+
+#: keystone/common/controller.py:18
+#, python-format
+msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
+msgstr ""
+
+#: keystone/common/controller.py:25
+msgid "RBAC: Invalid token"
+msgstr ""
+
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
+msgid "RBAC: Invalid user"
+msgstr ""
+
+#: keystone/common/controller.py:45
+msgid "RBAC: Proceeding without project"
+msgstr ""
+
+#: keystone/common/controller.py:65
+msgid "RBAC: Proceeding without tenant"
+msgstr ""
+
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
+msgid "RBAC: Bypassing authorization"
+msgstr ""
+
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
+msgid "RBAC: Authorization granted"
+msgstr ""
+
+#: keystone/common/controller.py:134
+#, python-format
+msgid "RBAC: Adding query filter params (%s)"
+msgstr ""
+
+#: keystone/common/controller.py:322
+msgid "Invalid token in normalize_domain_id"
+msgstr ""
+
+#: keystone/common/utils.py:233
+msgid ""
+"Error setting up the debug environment. Verify that the option --debug-"
+"url has the format <host>:<port> and that a debugger processes is "
+"listening on that port."
+msgstr ""
+
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
+#, python-format
+msgid "arg_dict: %s"
+msgstr ""
+
+#: keystone/common/wsgi.py:243
+#, python-format
+msgid "Authorization failed. %(exception)s from %(remote_addr)s"
+msgstr ""
+
+#: keystone/common/wsgi.py:487
+msgid "The resource could not be found."
+msgstr ""
+
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
+#, python-format
+msgid "Starting %(arg0)s on %(host)s:%(port)s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:113
+msgid "Server error"
+msgstr ""
+
+#: keystone/common/ldap/core.py:79
+#, python-format
+msgid "Invalid LDAP deref option: %s. Choose one of: "
+msgstr ""
+
+#: keystone/common/ldap/core.py:87
+#, python-format
+msgid "Invalid LDAP TLS certs option: %(option). Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:99
+#, python-format
+msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:189
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%s\". Format must be "
+"<ldap_attribute>:<keystone_attribute>"
+msgstr ""
+
+#: keystone/common/ldap/core.py:195
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%(item)s\". Value "
+"\"%(attr_map)s\" must use one of %(keys)s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
+#, python-format
+msgid "Duplicate name, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
+#, python-format
+msgid "Duplicate ID, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:294
+#, python-format
+msgid "LDAP %s create"
+msgstr ""
+
+#: keystone/common/ldap/core.py:372
+#, python-format
+msgid "LDAP %s update"
+msgstr ""
+
+#: keystone/common/ldap/core.py:405
+#, python-format
+msgid "LDAP %s delete"
+msgstr ""
+
+#: keystone/common/ldap/core.py:430
+#, python-format
+msgid "LDAP init: url=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:431
+#, python-format
+msgid ""
+"LDAP init: use_tls=%(use_tls)s\n"
+"tls_cacertfile=%(tls_cacertfile)s\n"
+"tls_cacertdir=%(tls_cacertdir)s\n"
+"tls_req_cert=%(tls_req_cert)s\n"
+"tls_avail=%(tls_avail)s\n"
+msgstr ""
+
+#: keystone/common/ldap/core.py:450
+msgid "Invalid TLS / LDAPS combination"
+msgstr ""
+
+#: keystone/common/ldap/core.py:454
+#, python-format
+msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available"
+msgstr ""
+
+#: keystone/common/ldap/core.py:464
+#, python-format
+msgid "tls_cacertfile %s not found or is not a file"
+msgstr ""
+
+#: keystone/common/ldap/core.py:476
+#, python-format
+msgid "tls_cacertdir %s not found or is not a directory"
+msgstr ""
+
+#: keystone/common/ldap/core.py:483
+#, python-format
+msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:497
+#, python-format
+msgid "LDAP bind: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:508
+#, python-format
+msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:514
+#, python-format
+msgid ""
+"LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, "
+"attrs=%(attrlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:567
+msgid ""
+"LDAP Server does not support paging. Disable paging in keystone.conf to "
+"avoid this message."
+msgstr ""
+
+#: keystone/common/ldap/core.py:584
+#, python-format
+msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:590
+#, python-format
+msgid "LDAP delete: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:595
+#, python-format
+msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:146
+#, python-format
+msgid "FakeLdap initialize url=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:156
+#, python-format
+msgid "FakeLdap bind dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:163
+#, python-format
+msgid "FakeLdap bind fail: dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:170
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:175
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s does not match"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:190
+#, python-format
+msgid "FakeLdap add item: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:193
+#, python-format
+msgid "FakeLdap add item failed: dn=%s is already in store."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:207 keystone/common/ldap/fakeldap.py:221
+#, python-format
+msgid "FakeLdap delete item: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:211 keystone/common/ldap/fakeldap.py:225
+#, python-format
+msgid "FakeLdap delete item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:240
+#, python-format
+msgid "FakeLdap modify item: dn=%(dn)s attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:245
+#, python-format
+msgid "FakeLdap modify item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:262
+#, python-format
+msgid "FakeLdap modify item failed: item has no attribute \"%s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:273
+#, python-format
+msgid ""
+"FakeLdap modify item failed: item has no attribute \"%(k)s\" with value "
+"\"%(v)s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:279
+#, python-format
+msgid "FakeLdap modify item failed: unknown command %s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:281
+#, python-format
+msgid "modify_s action %s not implemented"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:300
+#, python-format
+msgid "FakeLdap search at dn=%(dn)s scope=%(scope)s query=%(query)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:306
+msgid "FakeLdap search fail: dn not found for SCOPE_BASE"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:320
+#, python-format
+msgid "Search scope %s not implemented."
+msgstr ""
+
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
+#, python-format
+msgid "Got mysql server has gone away: %s"
+msgstr ""
+
+#: keystone/common/sql/legacy.py:188
+#, python-format
+msgid "Cannot migrate EC2 credential: %s"
+msgstr ""
+
+#: keystone/common/sql/migration.py:47
+msgid "version should be an integer"
+msgstr ""
+
+#: keystone/common/sql/nova.py:65
+#, python-format
+msgid "Create tenant %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:82
+#, python-format
+msgid "Create user %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:91
+#, python-format
+msgid "Add user %(user_id)s to tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:100
+#, python-format
+msgid "Ignoring existing role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:107
+#, python-format
+msgid "Create role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:117
+#, python-format
+msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:136
+#, python-format
+msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/identity/controllers.py:952
+#, python-format
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
+msgstr ""
+
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
+msgid "User not found in group"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:189
+#, python-format
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:334
+msgid "Changing Name not supported by LDAP"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:347
+#, python-format
+msgid "User %(user_id)s is already a member of group %(group_id)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:394
+#, python-format
+msgid "Failed to understand rule %(rule)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:404
+#, python-format
+msgid "No handler for matches of kind %s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:679
+#, python-format
+msgid "Failed to understand rule %(rule)r"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
+#: keystone/policy/backends/rules.py:93
+#, python-format
+msgid "enforce %(action)s: %(credentials)s"
+msgstr ""
+
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
+msgid "Token does not belong to specified tenant."
+msgstr ""
+
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
+msgstr ""
+
+#: keystone/token/backends/memcache.py:144
+#, python-format
+msgid ""
+"Successful set of token-index-list for user-key \"%(user_key)s\", "
+"#%(count)d records"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:154
+#, python-format
+msgid ""
+"Failed to set token-index-list for user-key \"%(user_key)s\". Attempt "
+"%(cas_retry)d of %(cas_retry_max)d"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:163
+msgid "Unable to add token user list"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:172
+msgid "Unable to add token to revocation list."
+msgstr ""
+
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
diff --git a/keystone/locale/en_US/LC_MESSAGES/keystone.po b/keystone/locale/en_US/LC_MESSAGES/keystone.po
new file mode 100644
index 00000000..c440b653
--- /dev/null
+++ b/keystone/locale/en_US/LC_MESSAGES/keystone.po
@@ -0,0 +1,847 @@
+# English (United States) translations for keystone.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the keystone project.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: Keystone\n"
+"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
+"PO-Revision-Date: 2013-07-29 22:01+0000\n"
+"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
+"Language-Team: English (United States) "
+"(http://www.transifex.com/projects/p/openstack/language/en_US/)\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: keystone/clean.py:23
+#, python-format
+msgid "%s cannot be empty."
+msgstr ""
+
+#: keystone/clean.py:25
+#, python-format
+msgid "%(property_name)s cannot be less than %(min_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:29
+#, python-format
+msgid "%(property_name)s should not be greater than %(max_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:36
+#, python-format
+msgid "%(property_name)s is not a %(display_expected_type)s"
+msgstr ""
+
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
+#: keystone/test.py:117
+#, python-format
+msgid "Failed to checkout %s"
+msgstr ""
+
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr ""
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr ""
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
+#, python-format
+msgid "Project is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
+#, python-format
+msgid "Domain is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
+#, python-format
+msgid "User is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:262
+msgid "Scoping to both domain and project is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:265
+msgid "Scoping to both domain and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:268
+msgid "Scoping to both project and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:353
+msgid "User not found"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
+#, python-format
+msgid "Unable to lookup user %s"
+msgstr ""
+
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
+msgstr ""
+
+#: keystone/catalog/core.py:38
+#, python-format
+msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s"
+msgstr ""
+
+#: keystone/catalog/core.py:43
+#, python-format
+msgid ""
+"Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing "
+"brackets ?)"
+msgstr ""
+
+#: keystone/catalog/core.py:49
+#, python-format
+msgid ""
+"Malformed endpoint %s - incomplete format (are you "
+"missing a type notifier ?)"
+msgstr ""
+
+#: keystone/catalog/backends/templated.py:109
+#, python-format
+msgid "Unable to open template file %s"
+msgstr ""
+
+#: keystone/common/cms.py:26
+#, python-format
+msgid "Verify error: %s"
+msgstr ""
+
+#: keystone/common/cms.py:118
+msgid ""
+"Signing error: Unable to load certificate - ensure you've configured PKI "
+"with 'keystone-manage pki_setup'"
+msgstr ""
+
+#: keystone/common/cms.py:122
+#, python-format
+msgid "Signing error: %s"
+msgstr ""
+
+#: keystone/common/config.py:89
+#, python-format
+msgid "Unable to locate specified logging config file: %s"
+msgstr ""
+
+#: keystone/common/config.py:107
+msgid "Invalid syslog facility"
+msgstr ""
+
+#: keystone/common/controller.py:18
+#, python-format
+msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
+msgstr ""
+
+#: keystone/common/controller.py:25
+msgid "RBAC: Invalid token"
+msgstr ""
+
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
+msgid "RBAC: Invalid user"
+msgstr ""
+
+#: keystone/common/controller.py:45
+msgid "RBAC: Proceeding without project"
+msgstr ""
+
+#: keystone/common/controller.py:65
+msgid "RBAC: Proceeding without tenant"
+msgstr ""
+
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
+msgid "RBAC: Bypassing authorization"
+msgstr ""
+
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
+msgid "RBAC: Authorization granted"
+msgstr ""
+
+#: keystone/common/controller.py:134
+#, python-format
+msgid "RBAC: Adding query filter params (%s)"
+msgstr ""
+
+#: keystone/common/controller.py:322
+msgid "Invalid token in normalize_domain_id"
+msgstr ""
+
+#: keystone/common/utils.py:233
+msgid ""
+"Error setting up the debug environment. Verify that the option --debug-"
+"url has the format <host>:<port> and that a debugger processes is "
+"listening on that port."
+msgstr ""
+
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
+#, python-format
+msgid "arg_dict: %s"
+msgstr ""
+
+#: keystone/common/wsgi.py:243
+#, python-format
+msgid "Authorization failed. %(exception)s from %(remote_addr)s"
+msgstr ""
+
+#: keystone/common/wsgi.py:487
+msgid "The resource could not be found."
+msgstr ""
+
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
+#, python-format
+msgid "Starting %(arg0)s on %(host)s:%(port)s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:113
+msgid "Server error"
+msgstr ""
+
+#: keystone/common/ldap/core.py:79
+#, python-format
+msgid "Invalid LDAP deref option: %s. Choose one of: "
+msgstr ""
+
+#: keystone/common/ldap/core.py:87
+#, python-format
+msgid "Invalid LDAP TLS certs option: %(option). Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:99
+#, python-format
+msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:189
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%s\". Format must be "
+"<ldap_attribute>:<keystone_attribute>"
+msgstr ""
+
+#: keystone/common/ldap/core.py:195
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%(item)s\". Value "
+"\"%(attr_map)s\" must use one of %(keys)s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
+#, python-format
+msgid "Duplicate name, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
+#, python-format
+msgid "Duplicate ID, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:294
+#, python-format
+msgid "LDAP %s create"
+msgstr ""
+
+#: keystone/common/ldap/core.py:372
+#, python-format
+msgid "LDAP %s update"
+msgstr ""
+
+#: keystone/common/ldap/core.py:405
+#, python-format
+msgid "LDAP %s delete"
+msgstr ""
+
+#: keystone/common/ldap/core.py:430
+#, python-format
+msgid "LDAP init: url=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:431
+#, python-format
+msgid ""
+"LDAP init: use_tls=%(use_tls)s\n"
+"tls_cacertfile=%(tls_cacertfile)s\n"
+"tls_cacertdir=%(tls_cacertdir)s\n"
+"tls_req_cert=%(tls_req_cert)s\n"
+"tls_avail=%(tls_avail)s\n"
+msgstr ""
+
+#: keystone/common/ldap/core.py:450
+msgid "Invalid TLS / LDAPS combination"
+msgstr ""
+
+#: keystone/common/ldap/core.py:454
+#, python-format
+msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available"
+msgstr ""
+
+#: keystone/common/ldap/core.py:464
+#, python-format
+msgid "tls_cacertfile %s not found or is not a file"
+msgstr ""
+
+#: keystone/common/ldap/core.py:476
+#, python-format
+msgid "tls_cacertdir %s not found or is not a directory"
+msgstr ""
+
+#: keystone/common/ldap/core.py:483
+#, python-format
+msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:497
+#, python-format
+msgid "LDAP bind: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:508
+#, python-format
+msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:514
+#, python-format
+msgid ""
+"LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, "
+"attrs=%(attrlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:567
+msgid ""
+"LDAP Server does not support paging. Disable paging in keystone.conf to "
+"avoid this message."
+msgstr ""
+
+#: keystone/common/ldap/core.py:584
+#, python-format
+msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:590
+#, python-format
+msgid "LDAP delete: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:595
+#, python-format
+msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:146
+#, python-format
+msgid "FakeLdap initialize url=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:156
+#, python-format
+msgid "FakeLdap bind dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:163
+#, python-format
+msgid "FakeLdap bind fail: dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:170
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:175
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s does not match"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:190
+#, python-format
+msgid "FakeLdap add item: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:193
+#, python-format
+msgid "FakeLdap add item failed: dn=%s is already in store."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:207 keystone/common/ldap/fakeldap.py:221
+#, python-format
+msgid "FakeLdap delete item: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:211 keystone/common/ldap/fakeldap.py:225
+#, python-format
+msgid "FakeLdap delete item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:240
+#, python-format
+msgid "FakeLdap modify item: dn=%(dn)s attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:245
+#, python-format
+msgid "FakeLdap modify item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:262
+#, python-format
+msgid "FakeLdap modify item failed: item has no attribute \"%s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:273
+#, python-format
+msgid ""
+"FakeLdap modify item failed: item has no attribute \"%(k)s\" with value "
+"\"%(v)s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:279
+#, python-format
+msgid "FakeLdap modify item failed: unknown command %s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:281
+#, python-format
+msgid "modify_s action %s not implemented"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:300
+#, python-format
+msgid "FakeLdap search at dn=%(dn)s scope=%(scope)s query=%(query)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:306
+msgid "FakeLdap search fail: dn not found for SCOPE_BASE"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:320
+#, python-format
+msgid "Search scope %s not implemented."
+msgstr ""
+
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
+#, python-format
+msgid "Got mysql server has gone away: %s"
+msgstr ""
+
+#: keystone/common/sql/legacy.py:188
+#, python-format
+msgid "Cannot migrate EC2 credential: %s"
+msgstr ""
+
+#: keystone/common/sql/migration.py:47
+msgid "version should be an integer"
+msgstr ""
+
+#: keystone/common/sql/nova.py:65
+#, python-format
+msgid "Create tenant %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:82
+#, python-format
+msgid "Create user %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:91
+#, python-format
+msgid "Add user %(user_id)s to tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:100
+#, python-format
+msgid "Ignoring existing role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:107
+#, python-format
+msgid "Create role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:117
+#, python-format
+msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:136
+#, python-format
+msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/identity/controllers.py:952
+#, python-format
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
+msgstr ""
+
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
+msgid "User not found in group"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:189
+#, python-format
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:334
+msgid "Changing Name not supported by LDAP"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:347
+#, python-format
+msgid "User %(user_id)s is already a member of group %(group_id)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:394
+#, python-format
+msgid "Failed to understand rule %(rule)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:404
+#, python-format
+msgid "No handler for matches of kind %s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:679
+#, python-format
+msgid "Failed to understand rule %(rule)r"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
+#: keystone/policy/backends/rules.py:93
+#, python-format
+msgid "enforce %(action)s: %(credentials)s"
+msgstr ""
+
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
+msgid "Token does not belong to specified tenant."
+msgstr ""
+
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
+msgstr ""
+
+#: keystone/token/backends/memcache.py:144
+#, python-format
+msgid ""
+"Successful set of token-index-list for user-key \"%(user_key)s\", "
+"#%(count)d records"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:154
+#, python-format
+msgid ""
+"Failed to set token-index-list for user-key \"%(user_key)s\". Attempt "
+"%(cas_retry)d of %(cas_retry_max)d"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:163
+msgid "Unable to add token user list"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:172
+msgid "Unable to add token to revocation list."
+msgstr ""
+
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
diff --git a/keystone/locale/es/LC_MESSAGES/keystone.po b/keystone/locale/es/LC_MESSAGES/keystone.po
index 8cd820d9..b97acbc8 100644
--- a/keystone/locale/es/LC_MESSAGES/keystone.po
+++ b/keystone/locale/es/LC_MESSAGES/keystone.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Keystone\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2013-06-17 17:09+0000\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
"PO-Revision-Date: 2013-05-21 09:13+0000\n"
"Last-Translator: daisy.ycguo <daisy.ycguo@gmail.com>\n"
"Language-Team: Spanish "
@@ -16,7 +16,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.6\n"
+"Generated-By: Babel 1.3\n"
#: keystone/clean.py:23
#, python-format
@@ -38,65 +38,225 @@ msgstr "%(property_name)s no debe tener más de %(max_length)s caracteres."
msgid "%(property_name)s is not a %(display_expected_type)s"
msgstr ""
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
#: keystone/test.py:117
#, python-format
msgid "Failed to checkout %s"
msgstr "No se ha podido extraer %s"
-#: keystone/auth/controllers.py:72
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr "No se puede eliminar un rol que no se ha otorgado, %s"
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr "No se ha encontrado el rol %s"
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
#, python-format
msgid "Project is disabled: %s"
msgstr "El proyecto está inhabilitado: %s"
-#: keystone/auth/controllers.py:78 keystone/auth/plugins/password.py:39
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
#, python-format
msgid "Domain is disabled: %s"
msgstr "El dominio está inhabilitado: %s"
-#: keystone/auth/controllers.py:84 keystone/auth/plugins/password.py:45
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
#, python-format
msgid "User is disabled: %s"
msgstr "El usuario está inhabilitado: %s"
-#: keystone/auth/controllers.py:265
+#: keystone/auth/controllers.py:262
msgid "Scoping to both domain and project is not allowed"
msgstr "El ámbito para dominio y proyecto no está permitido"
-#: keystone/auth/controllers.py:268
+#: keystone/auth/controllers.py:265
msgid "Scoping to both domain and trust is not allowed"
msgstr "El ámbito para dominio y confianza no está permitido"
-#: keystone/auth/controllers.py:271
+#: keystone/auth/controllers.py:268
msgid "Scoping to both project and trust is not allowed"
msgstr "El ámbito para proyecto y confianza no está permitido"
-#: keystone/auth/controllers.py:333
-#, python-format
-msgid "Unable to lookup user %s"
-msgstr "No se ha podido buscar el usuario %s"
-
-#: keystone/auth/controllers.py:363
+#: keystone/auth/controllers.py:353
msgid "User not found"
msgstr "Usuario no encontrado"
-#: keystone/auth/token_factory.py:81
-msgid "User have no access to project"
-msgstr "El usuario no tiene acceso al proyecto"
-
-#: keystone/auth/token_factory.py:96
-msgid "User have no access to domain"
-msgstr "El usuario no tiene acceso al dominio"
-
-#: keystone/auth/token_factory.py:314 keystone/token/controllers.py:121
-msgid "Unable to sign token."
-msgstr "No se ha podido firmar la señal."
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
+msgstr ""
-#: keystone/auth/token_factory.py:317 keystone/token/controllers.py:124
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
#, python-format
-msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+msgid "Unable to lookup user %s"
+msgstr "No se ha podido buscar el usuario %s"
+
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
msgstr ""
-"Valor no válido para token_format: %s. Los valores permitidos son PKI o "
-"UUID."
#: keystone/catalog/core.py:38
#, python-format
@@ -128,12 +288,12 @@ msgstr ""
msgid "Unable to open template file %s"
msgstr "No se puede abrir el archivo de plantilla %s"
-#: keystone/common/cms.py:42
+#: keystone/common/cms.py:26
#, python-format
msgid "Verify error: %s"
msgstr "Verificar error: %s"
-#: keystone/common/cms.py:134
+#: keystone/common/cms.py:118
msgid ""
"Signing error: Unable to load certificate - ensure you've configured PKI "
"with 'keystone-manage pki_setup'"
@@ -141,7 +301,7 @@ msgstr ""
"Error de firma: no se ha podido cargar el certificado; asegúrese de haber"
" configurado la PKI con 'keystone-manage pki_setup'"
-#: keystone/common/cms.py:138
+#: keystone/common/cms.py:122
#, python-format
msgid "Signing error: %s"
msgstr "Error de firma: %s"
@@ -162,31 +322,31 @@ msgstr "Recurso syslog no válido"
msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
msgstr ""
-#: keystone/common/controller.py:26
+#: keystone/common/controller.py:25
msgid "RBAC: Invalid token"
msgstr "RBAC: Señal no válida"
-#: keystone/common/controller.py:36 keystone/common/controller.py:57
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
msgid "RBAC: Invalid user"
msgstr "RBAC: Usuario no válido"
-#: keystone/common/controller.py:42
+#: keystone/common/controller.py:45
msgid "RBAC: Proceeding without project"
msgstr "RBAC: continuando sin proyecto"
-#: keystone/common/controller.py:62
+#: keystone/common/controller.py:65
msgid "RBAC: Proceeding without tenant"
msgstr "RBAC: Continuando sin arrendatario"
-#: keystone/common/controller.py:92 keystone/common/controller.py:144
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
msgid "RBAC: Bypassing authorization"
msgstr "RBAC: Eludiendo autorización"
-#: keystone/common/controller.py:101 keystone/common/controller.py:142
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
msgid "RBAC: Authorization granted"
msgstr "RBAC: Autorización otorgada"
-#: keystone/common/controller.py:131
+#: keystone/common/controller.py:134
#, python-format
msgid "RBAC: Adding query filter params (%s)"
msgstr "RBAC: añadiendo parámetros de filtro de consultas (%s)"
@@ -195,33 +355,69 @@ msgstr "RBAC: añadiendo parámetros de filtro de consultas (%s)"
msgid "Invalid token in normalize_domain_id"
msgstr "Señal no válida en normalize_domain_id"
-#: keystone/common/utils.py:232
+#: keystone/common/utils.py:233
msgid ""
"Error setting up the debug environment. Verify that the option --debug-"
"url has the format <host>:<port> and that a debugger processes is "
"listening on that port."
msgstr ""
-#: keystone/common/wsgi.py:162
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
#, python-format
msgid "arg_dict: %s"
msgstr "arg_dict: %s"
-#: keystone/common/wsgi.py:186
+#: keystone/common/wsgi.py:243
#, fuzzy, python-format
msgid "Authorization failed. %(exception)s from %(remote_addr)s"
msgstr "Ha fallado la autorización. %s de %s"
-#: keystone/common/wsgi.py:429
+#: keystone/common/wsgi.py:487
msgid "The resource could not be found."
msgstr "El recurso no se ha podido encontrar."
-#: keystone/common/wsgi_server.py:72
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
#, python-format
msgid "Starting %(arg0)s on %(host)s:%(port)s"
msgstr "Iniciando %(arg0)s en %(host)s:%(port)s"
-#: keystone/common/wsgi_server.py:132
+#: keystone/common/environment/eventlet_server.py:113
msgid "Server error"
msgstr "Error de servidor"
@@ -254,13 +450,13 @@ msgid ""
"\"%(attr_map)s\" must use one of %(keys)s."
msgstr ""
-#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:596
-#: keystone/identity/backends/kvs.py:624
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
#, python-format
msgid "Duplicate name, %s."
msgstr "Nombre duplicado, %s."
-#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:589
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
#, python-format
msgid "Duplicate ID, %s."
msgstr "ID duplicado, %s."
@@ -461,12 +657,16 @@ msgstr ""
msgid "Search scope %s not implemented."
msgstr "Ãmbito de búsqueda %s no implementado."
-#: keystone/common/sql/core.py:205
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
#, python-format
msgid "Got mysql server has gone away: %s"
msgstr "Se ha notificado que mysql server ha desaparecido: %s"
-#: keystone/common/sql/legacy.py:180
+#: keystone/common/sql/legacy.py:188
#, python-format
msgid "Cannot migrate EC2 credential: %s"
msgstr "No se puede migrar la credencial EC2: %s "
@@ -475,76 +675,68 @@ msgstr "No se puede migrar la credencial EC2: %s "
msgid "version should be an integer"
msgstr "la versión debe ser un entero"
-#: keystone/common/sql/nova.py:62
+#: keystone/common/sql/nova.py:65
#, python-format
msgid "Create tenant %s"
msgstr "Crear el arrendatario %s"
-#: keystone/common/sql/nova.py:79
+#: keystone/common/sql/nova.py:82
#, python-format
msgid "Create user %s"
msgstr "Crear el usuario %s"
-#: keystone/common/sql/nova.py:88
+#: keystone/common/sql/nova.py:91
#, fuzzy, python-format
msgid "Add user %(user_id)s to tenant %(tenant_id)s"
msgstr "Añadir el usuario %s al arrendatario %s"
-#: keystone/common/sql/nova.py:97
+#: keystone/common/sql/nova.py:100
#, python-format
msgid "Ignoring existing role %s"
msgstr "Ignorando el rol existente %s"
-#: keystone/common/sql/nova.py:104
+#: keystone/common/sql/nova.py:107
#, python-format
msgid "Create role %s"
msgstr "Crear el rol %s"
-#: keystone/common/sql/nova.py:114
+#: keystone/common/sql/nova.py:117
#, fuzzy, python-format
msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
msgstr "Asignar el rol %s al usuario %s en el arrendatario %s"
-#: keystone/common/sql/nova.py:133
+#: keystone/common/sql/nova.py:136
#, fuzzy, python-format
msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
msgstr "Creando credencial ec2 para el usuario %s y el arrendatario %s"
-#: keystone/identity/backends/kvs.py:250 keystone/identity/backends/kvs.py:259
+#: keystone/identity/controllers.py:952
+#, python-format
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
+msgstr ""
+
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
msgid "User not found in group"
msgstr "Usuario no encontrado en grupo"
-#: keystone/identity/backends/sql.py:425
-#, python-format
-msgid "Cannot remove role that has not been granted, %s"
-msgstr "No se puede eliminar un rol que no se ha otorgado, %s"
-
-#: keystone/identity/backends/ldap/core.py:82
+#: keystone/identity/backends/ldap.py:189
#, python-format
-msgid "Expected dict or list: %s"
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
msgstr ""
-#: keystone/identity/backends/ldap/core.py:681
-#, python-format
-msgid "Role %s not found"
-msgstr "No se ha encontrado el rol %s"
-
-#: keystone/identity/backends/ldap/core.py:898
+#: keystone/identity/backends/ldap.py:334
msgid "Changing Name not supported by LDAP"
msgstr "LDAP no soporta el cambio de nombre"
-#: keystone/identity/backends/ldap/core.py:911
+#: keystone/identity/backends/ldap.py:347
#, fuzzy, python-format
msgid "User %(user_id)s is already a member of group %(group_id)s"
msgstr "El usuario %s ya es miembro del grupo %s"
-#: keystone/identity/backends/ldap/core.py:954
-#, python-format
-msgid ""
-"Group member '%(user_dn)s' not found in '%(group_dn)s'. The user should "
-"be removed from the group. The user will be ignored."
-msgstr ""
-
#: keystone/openstack/common/policy.py:394
#, python-format
msgid "Failed to understand rule %(rule)s"
@@ -560,22 +752,57 @@ msgstr "No hay manejador para coincidencias de clase %s"
msgid "Failed to understand rule %(rule)r"
msgstr "No se ha podido comprender la regla %(rule)r"
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
#: keystone/policy/backends/rules.py:93
#, python-format
msgid "enforce %(action)s: %(credentials)s"
msgstr ""
-#: keystone/token/controllers.py:465 keystone/token/controllers.py:468
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
msgid "Token does not belong to specified tenant."
msgstr "La señal no pertenece al arrendatario especificado."
-#: keystone/token/controllers.py:475
-msgid "Non-default domain is not supported"
-msgstr "El dominio no predeterminado no está soportado"
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
+msgstr ""
-#: keystone/token/controllers.py:483
-msgid "Domain scoped token is not supported"
-msgstr "La señal con ámbito de dominio no está soportada"
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
+msgstr ""
#: keystone/token/backends/memcache.py:144
#, python-format
@@ -599,3 +826,57 @@ msgstr ""
msgid "Unable to add token to revocation list."
msgstr "No se puede añadir señal a lista de revocación. "
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr "No se ha podido firmar la señal."
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr "El dominio no predeterminado no está soportado"
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr "La señal con ámbito de dominio no está soportada"
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
+#~ msgid "User have no access to project"
+#~ msgstr "El usuario no tiene acceso al proyecto"
+
+#~ msgid "User have no access to domain"
+#~ msgstr "El usuario no tiene acceso al dominio"
+
+#~ msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+#~ msgstr ""
+#~ "Valor no válido para token_format: %s."
+#~ " Los valores permitidos son PKI o "
+#~ "UUID."
+
diff --git a/keystone/locale/fi_FI/LC_MESSAGES/keystone.po b/keystone/locale/fi_FI/LC_MESSAGES/keystone.po
index cb839c03..cda26e08 100644
--- a/keystone/locale/fi_FI/LC_MESSAGES/keystone.po
+++ b/keystone/locale/fi_FI/LC_MESSAGES/keystone.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Keystone\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2013-06-17 17:09+0000\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
"PO-Revision-Date: 2013-05-17 16:06+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
"Language-Team: Finnish (Finland) "
@@ -16,7 +16,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.6\n"
+"Generated-By: Babel 1.3\n"
#: keystone/clean.py:23
#, python-format
@@ -38,62 +38,224 @@ msgstr ""
msgid "%(property_name)s is not a %(display_expected_type)s"
msgstr ""
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
#: keystone/test.py:117
#, python-format
msgid "Failed to checkout %s"
msgstr ""
-#: keystone/auth/controllers.py:72
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr ""
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr ""
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
#, python-format
msgid "Project is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:78 keystone/auth/plugins/password.py:39
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
#, python-format
msgid "Domain is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:84 keystone/auth/plugins/password.py:45
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
#, python-format
msgid "User is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:265
+#: keystone/auth/controllers.py:262
msgid "Scoping to both domain and project is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:268
+#: keystone/auth/controllers.py:265
msgid "Scoping to both domain and trust is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:271
+#: keystone/auth/controllers.py:268
msgid "Scoping to both project and trust is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:333
-#, python-format
-msgid "Unable to lookup user %s"
-msgstr ""
-
-#: keystone/auth/controllers.py:363
+#: keystone/auth/controllers.py:353
msgid "User not found"
msgstr ""
-#: keystone/auth/token_factory.py:81
-msgid "User have no access to project"
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
msgstr ""
-#: keystone/auth/token_factory.py:96
-msgid "User have no access to domain"
-msgstr ""
-
-#: keystone/auth/token_factory.py:314 keystone/token/controllers.py:121
-msgid "Unable to sign token."
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
+#, python-format
+msgid "Unable to lookup user %s"
msgstr ""
-#: keystone/auth/token_factory.py:317 keystone/token/controllers.py:124
-#, python-format
-msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
msgstr ""
#: keystone/catalog/core.py:38
@@ -120,18 +282,18 @@ msgstr ""
msgid "Unable to open template file %s"
msgstr ""
-#: keystone/common/cms.py:42
+#: keystone/common/cms.py:26
#, python-format
msgid "Verify error: %s"
msgstr ""
-#: keystone/common/cms.py:134
+#: keystone/common/cms.py:118
msgid ""
"Signing error: Unable to load certificate - ensure you've configured PKI "
"with 'keystone-manage pki_setup'"
msgstr ""
-#: keystone/common/cms.py:138
+#: keystone/common/cms.py:122
#, python-format
msgid "Signing error: %s"
msgstr ""
@@ -150,31 +312,31 @@ msgstr ""
msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
msgstr ""
-#: keystone/common/controller.py:26
+#: keystone/common/controller.py:25
msgid "RBAC: Invalid token"
msgstr ""
-#: keystone/common/controller.py:36 keystone/common/controller.py:57
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
msgid "RBAC: Invalid user"
msgstr ""
-#: keystone/common/controller.py:42
+#: keystone/common/controller.py:45
msgid "RBAC: Proceeding without project"
msgstr ""
-#: keystone/common/controller.py:62
+#: keystone/common/controller.py:65
msgid "RBAC: Proceeding without tenant"
msgstr ""
-#: keystone/common/controller.py:92 keystone/common/controller.py:144
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
msgid "RBAC: Bypassing authorization"
msgstr ""
-#: keystone/common/controller.py:101 keystone/common/controller.py:142
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
msgid "RBAC: Authorization granted"
msgstr ""
-#: keystone/common/controller.py:131
+#: keystone/common/controller.py:134
#, python-format
msgid "RBAC: Adding query filter params (%s)"
msgstr ""
@@ -183,33 +345,69 @@ msgstr ""
msgid "Invalid token in normalize_domain_id"
msgstr ""
-#: keystone/common/utils.py:232
+#: keystone/common/utils.py:233
msgid ""
"Error setting up the debug environment. Verify that the option --debug-"
"url has the format <host>:<port> and that a debugger processes is "
"listening on that port."
msgstr ""
-#: keystone/common/wsgi.py:162
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
#, python-format
msgid "arg_dict: %s"
msgstr ""
-#: keystone/common/wsgi.py:186
+#: keystone/common/wsgi.py:243
#, python-format
msgid "Authorization failed. %(exception)s from %(remote_addr)s"
msgstr ""
-#: keystone/common/wsgi.py:429
+#: keystone/common/wsgi.py:487
msgid "The resource could not be found."
msgstr ""
-#: keystone/common/wsgi_server.py:72
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
#, python-format
msgid "Starting %(arg0)s on %(host)s:%(port)s"
msgstr ""
-#: keystone/common/wsgi_server.py:132
+#: keystone/common/environment/eventlet_server.py:113
msgid "Server error"
msgstr ""
@@ -242,13 +440,13 @@ msgid ""
"\"%(attr_map)s\" must use one of %(keys)s."
msgstr ""
-#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:596
-#: keystone/identity/backends/kvs.py:624
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
#, python-format
msgid "Duplicate name, %s."
msgstr ""
-#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:589
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
#, python-format
msgid "Duplicate ID, %s."
msgstr ""
@@ -436,12 +634,16 @@ msgstr ""
msgid "Search scope %s not implemented."
msgstr ""
-#: keystone/common/sql/core.py:205
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
#, python-format
msgid "Got mysql server has gone away: %s"
msgstr ""
-#: keystone/common/sql/legacy.py:180
+#: keystone/common/sql/legacy.py:188
#, python-format
msgid "Cannot migrate EC2 credential: %s"
msgstr ""
@@ -450,76 +652,68 @@ msgstr ""
msgid "version should be an integer"
msgstr ""
-#: keystone/common/sql/nova.py:62
+#: keystone/common/sql/nova.py:65
#, python-format
msgid "Create tenant %s"
msgstr ""
-#: keystone/common/sql/nova.py:79
+#: keystone/common/sql/nova.py:82
#, python-format
msgid "Create user %s"
msgstr ""
-#: keystone/common/sql/nova.py:88
+#: keystone/common/sql/nova.py:91
#, python-format
msgid "Add user %(user_id)s to tenant %(tenant_id)s"
msgstr ""
-#: keystone/common/sql/nova.py:97
+#: keystone/common/sql/nova.py:100
#, python-format
msgid "Ignoring existing role %s"
msgstr ""
-#: keystone/common/sql/nova.py:104
+#: keystone/common/sql/nova.py:107
#, python-format
msgid "Create role %s"
msgstr ""
-#: keystone/common/sql/nova.py:114
+#: keystone/common/sql/nova.py:117
#, python-format
msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
msgstr ""
-#: keystone/common/sql/nova.py:133
+#: keystone/common/sql/nova.py:136
#, python-format
msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
msgstr ""
-#: keystone/identity/backends/kvs.py:250 keystone/identity/backends/kvs.py:259
-msgid "User not found in group"
-msgstr ""
-
-#: keystone/identity/backends/sql.py:425
+#: keystone/identity/controllers.py:952
#, python-format
-msgid "Cannot remove role that has not been granted, %s"
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:82
-#, python-format
-msgid "Expected dict or list: %s"
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
+msgid "User not found in group"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:681
+#: keystone/identity/backends/ldap.py:189
#, python-format
-msgid "Role %s not found"
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
msgstr ""
-#: keystone/identity/backends/ldap/core.py:898
+#: keystone/identity/backends/ldap.py:334
msgid "Changing Name not supported by LDAP"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:911
+#: keystone/identity/backends/ldap.py:347
#, python-format
msgid "User %(user_id)s is already a member of group %(group_id)s"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:954
-#, python-format
-msgid ""
-"Group member '%(user_dn)s' not found in '%(group_dn)s'. The user should "
-"be removed from the group. The user will be ignored."
-msgstr ""
-
#: keystone/openstack/common/policy.py:394
#, python-format
msgid "Failed to understand rule %(rule)s"
@@ -535,21 +729,56 @@ msgstr ""
msgid "Failed to understand rule %(rule)r"
msgstr ""
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
#: keystone/policy/backends/rules.py:93
#, python-format
msgid "enforce %(action)s: %(credentials)s"
msgstr ""
-#: keystone/token/controllers.py:465 keystone/token/controllers.py:468
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
msgid "Token does not belong to specified tenant."
msgstr ""
-#: keystone/token/controllers.py:475
-msgid "Non-default domain is not supported"
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
msgstr ""
-#: keystone/token/controllers.py:483
-msgid "Domain scoped token is not supported"
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
msgstr ""
#: keystone/token/backends/memcache.py:144
@@ -574,3 +803,54 @@ msgstr ""
msgid "Unable to add token to revocation list."
msgstr ""
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
+#~ msgid "User have no access to project"
+#~ msgstr ""
+
+#~ msgid "User have no access to domain"
+#~ msgstr ""
+
+#~ msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+#~ msgstr ""
+
diff --git a/keystone/locale/fr/LC_MESSAGES/keystone.po b/keystone/locale/fr/LC_MESSAGES/keystone.po
index 048357e5..d2aced78 100644
--- a/keystone/locale/fr/LC_MESSAGES/keystone.po
+++ b/keystone/locale/fr/LC_MESSAGES/keystone.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Keystone\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2013-06-17 17:09+0000\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
"PO-Revision-Date: 2013-05-17 16:06+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
"Language-Team: French "
@@ -16,7 +16,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.6\n"
+"Generated-By: Babel 1.3\n"
#: keystone/clean.py:23
#, python-format
@@ -38,62 +38,224 @@ msgstr ""
msgid "%(property_name)s is not a %(display_expected_type)s"
msgstr ""
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
#: keystone/test.py:117
#, python-format
msgid "Failed to checkout %s"
msgstr ""
-#: keystone/auth/controllers.py:72
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr ""
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr ""
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
#, python-format
msgid "Project is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:78 keystone/auth/plugins/password.py:39
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
#, python-format
msgid "Domain is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:84 keystone/auth/plugins/password.py:45
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
#, python-format
msgid "User is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:265
+#: keystone/auth/controllers.py:262
msgid "Scoping to both domain and project is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:268
+#: keystone/auth/controllers.py:265
msgid "Scoping to both domain and trust is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:271
+#: keystone/auth/controllers.py:268
msgid "Scoping to both project and trust is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:333
-#, python-format
-msgid "Unable to lookup user %s"
-msgstr ""
-
-#: keystone/auth/controllers.py:363
+#: keystone/auth/controllers.py:353
msgid "User not found"
msgstr ""
-#: keystone/auth/token_factory.py:81
-msgid "User have no access to project"
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
msgstr ""
-#: keystone/auth/token_factory.py:96
-msgid "User have no access to domain"
-msgstr ""
-
-#: keystone/auth/token_factory.py:314 keystone/token/controllers.py:121
-msgid "Unable to sign token."
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
+#, python-format
+msgid "Unable to lookup user %s"
msgstr ""
-#: keystone/auth/token_factory.py:317 keystone/token/controllers.py:124
-#, python-format
-msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
msgstr ""
#: keystone/catalog/core.py:38
@@ -120,18 +282,18 @@ msgstr ""
msgid "Unable to open template file %s"
msgstr ""
-#: keystone/common/cms.py:42
+#: keystone/common/cms.py:26
#, python-format
msgid "Verify error: %s"
msgstr ""
-#: keystone/common/cms.py:134
+#: keystone/common/cms.py:118
msgid ""
"Signing error: Unable to load certificate - ensure you've configured PKI "
"with 'keystone-manage pki_setup'"
msgstr ""
-#: keystone/common/cms.py:138
+#: keystone/common/cms.py:122
#, python-format
msgid "Signing error: %s"
msgstr ""
@@ -150,31 +312,31 @@ msgstr ""
msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
msgstr ""
-#: keystone/common/controller.py:26
+#: keystone/common/controller.py:25
msgid "RBAC: Invalid token"
msgstr ""
-#: keystone/common/controller.py:36 keystone/common/controller.py:57
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
msgid "RBAC: Invalid user"
msgstr ""
-#: keystone/common/controller.py:42
+#: keystone/common/controller.py:45
msgid "RBAC: Proceeding without project"
msgstr ""
-#: keystone/common/controller.py:62
+#: keystone/common/controller.py:65
msgid "RBAC: Proceeding without tenant"
msgstr ""
-#: keystone/common/controller.py:92 keystone/common/controller.py:144
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
msgid "RBAC: Bypassing authorization"
msgstr ""
-#: keystone/common/controller.py:101 keystone/common/controller.py:142
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
msgid "RBAC: Authorization granted"
msgstr ""
-#: keystone/common/controller.py:131
+#: keystone/common/controller.py:134
#, python-format
msgid "RBAC: Adding query filter params (%s)"
msgstr ""
@@ -183,33 +345,69 @@ msgstr ""
msgid "Invalid token in normalize_domain_id"
msgstr ""
-#: keystone/common/utils.py:232
+#: keystone/common/utils.py:233
msgid ""
"Error setting up the debug environment. Verify that the option --debug-"
"url has the format <host>:<port> and that a debugger processes is "
"listening on that port."
msgstr ""
-#: keystone/common/wsgi.py:162
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
#, python-format
msgid "arg_dict: %s"
msgstr ""
-#: keystone/common/wsgi.py:186
+#: keystone/common/wsgi.py:243
#, python-format
msgid "Authorization failed. %(exception)s from %(remote_addr)s"
msgstr ""
-#: keystone/common/wsgi.py:429
+#: keystone/common/wsgi.py:487
msgid "The resource could not be found."
msgstr ""
-#: keystone/common/wsgi_server.py:72
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
#, python-format
msgid "Starting %(arg0)s on %(host)s:%(port)s"
msgstr ""
-#: keystone/common/wsgi_server.py:132
+#: keystone/common/environment/eventlet_server.py:113
msgid "Server error"
msgstr ""
@@ -242,13 +440,13 @@ msgid ""
"\"%(attr_map)s\" must use one of %(keys)s."
msgstr ""
-#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:596
-#: keystone/identity/backends/kvs.py:624
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
#, python-format
msgid "Duplicate name, %s."
msgstr ""
-#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:589
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
#, python-format
msgid "Duplicate ID, %s."
msgstr ""
@@ -436,12 +634,16 @@ msgstr ""
msgid "Search scope %s not implemented."
msgstr ""
-#: keystone/common/sql/core.py:205
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
#, python-format
msgid "Got mysql server has gone away: %s"
msgstr ""
-#: keystone/common/sql/legacy.py:180
+#: keystone/common/sql/legacy.py:188
#, python-format
msgid "Cannot migrate EC2 credential: %s"
msgstr ""
@@ -450,76 +652,68 @@ msgstr ""
msgid "version should be an integer"
msgstr ""
-#: keystone/common/sql/nova.py:62
+#: keystone/common/sql/nova.py:65
#, python-format
msgid "Create tenant %s"
msgstr ""
-#: keystone/common/sql/nova.py:79
+#: keystone/common/sql/nova.py:82
#, python-format
msgid "Create user %s"
msgstr ""
-#: keystone/common/sql/nova.py:88
+#: keystone/common/sql/nova.py:91
#, python-format
msgid "Add user %(user_id)s to tenant %(tenant_id)s"
msgstr ""
-#: keystone/common/sql/nova.py:97
+#: keystone/common/sql/nova.py:100
#, python-format
msgid "Ignoring existing role %s"
msgstr ""
-#: keystone/common/sql/nova.py:104
+#: keystone/common/sql/nova.py:107
#, python-format
msgid "Create role %s"
msgstr ""
-#: keystone/common/sql/nova.py:114
+#: keystone/common/sql/nova.py:117
#, python-format
msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
msgstr ""
-#: keystone/common/sql/nova.py:133
+#: keystone/common/sql/nova.py:136
#, python-format
msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
msgstr ""
-#: keystone/identity/backends/kvs.py:250 keystone/identity/backends/kvs.py:259
-msgid "User not found in group"
-msgstr ""
-
-#: keystone/identity/backends/sql.py:425
+#: keystone/identity/controllers.py:952
#, python-format
-msgid "Cannot remove role that has not been granted, %s"
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:82
-#, python-format
-msgid "Expected dict or list: %s"
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
+msgid "User not found in group"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:681
+#: keystone/identity/backends/ldap.py:189
#, python-format
-msgid "Role %s not found"
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
msgstr ""
-#: keystone/identity/backends/ldap/core.py:898
+#: keystone/identity/backends/ldap.py:334
msgid "Changing Name not supported by LDAP"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:911
+#: keystone/identity/backends/ldap.py:347
#, python-format
msgid "User %(user_id)s is already a member of group %(group_id)s"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:954
-#, python-format
-msgid ""
-"Group member '%(user_dn)s' not found in '%(group_dn)s'. The user should "
-"be removed from the group. The user will be ignored."
-msgstr ""
-
#: keystone/openstack/common/policy.py:394
#, python-format
msgid "Failed to understand rule %(rule)s"
@@ -535,21 +729,56 @@ msgstr ""
msgid "Failed to understand rule %(rule)r"
msgstr ""
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
#: keystone/policy/backends/rules.py:93
#, python-format
msgid "enforce %(action)s: %(credentials)s"
msgstr ""
-#: keystone/token/controllers.py:465 keystone/token/controllers.py:468
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
msgid "Token does not belong to specified tenant."
msgstr ""
-#: keystone/token/controllers.py:475
-msgid "Non-default domain is not supported"
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
msgstr ""
-#: keystone/token/controllers.py:483
-msgid "Domain scoped token is not supported"
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
msgstr ""
#: keystone/token/backends/memcache.py:144
@@ -574,3 +803,54 @@ msgstr ""
msgid "Unable to add token to revocation list."
msgstr ""
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
+#~ msgid "User have no access to project"
+#~ msgstr ""
+
+#~ msgid "User have no access to domain"
+#~ msgstr ""
+
+#~ msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+#~ msgstr ""
+
diff --git a/keystone/locale/hr/LC_MESSAGES/keystone.po b/keystone/locale/hr/LC_MESSAGES/keystone.po
new file mode 100644
index 00000000..8c5e03f5
--- /dev/null
+++ b/keystone/locale/hr/LC_MESSAGES/keystone.po
@@ -0,0 +1,848 @@
+# Croatian translations for keystone.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the keystone project.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: Keystone\n"
+"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
+"PO-Revision-Date: 2013-07-29 22:01+0000\n"
+"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
+"Language-Team: Croatian "
+"(http://www.transifex.com/projects/p/openstack/language/hr/)\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 1.3\n"
+
+#: keystone/clean.py:23
+#, python-format
+msgid "%s cannot be empty."
+msgstr ""
+
+#: keystone/clean.py:25
+#, python-format
+msgid "%(property_name)s cannot be less than %(min_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:29
+#, python-format
+msgid "%(property_name)s should not be greater than %(max_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:36
+#, python-format
+msgid "%(property_name)s is not a %(display_expected_type)s"
+msgstr ""
+
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
+#: keystone/test.py:117
+#, python-format
+msgid "Failed to checkout %s"
+msgstr ""
+
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr ""
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr ""
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
+#, python-format
+msgid "Project is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
+#, python-format
+msgid "Domain is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
+#, python-format
+msgid "User is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:262
+msgid "Scoping to both domain and project is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:265
+msgid "Scoping to both domain and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:268
+msgid "Scoping to both project and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:353
+msgid "User not found"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
+#, python-format
+msgid "Unable to lookup user %s"
+msgstr ""
+
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
+msgstr ""
+
+#: keystone/catalog/core.py:38
+#, python-format
+msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s"
+msgstr ""
+
+#: keystone/catalog/core.py:43
+#, python-format
+msgid ""
+"Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing "
+"brackets ?)"
+msgstr ""
+
+#: keystone/catalog/core.py:49
+#, python-format
+msgid ""
+"Malformed endpoint %s - incomplete format (are you "
+"missing a type notifier ?)"
+msgstr ""
+
+#: keystone/catalog/backends/templated.py:109
+#, python-format
+msgid "Unable to open template file %s"
+msgstr ""
+
+#: keystone/common/cms.py:26
+#, python-format
+msgid "Verify error: %s"
+msgstr ""
+
+#: keystone/common/cms.py:118
+msgid ""
+"Signing error: Unable to load certificate - ensure you've configured PKI "
+"with 'keystone-manage pki_setup'"
+msgstr ""
+
+#: keystone/common/cms.py:122
+#, python-format
+msgid "Signing error: %s"
+msgstr ""
+
+#: keystone/common/config.py:89
+#, python-format
+msgid "Unable to locate specified logging config file: %s"
+msgstr ""
+
+#: keystone/common/config.py:107
+msgid "Invalid syslog facility"
+msgstr ""
+
+#: keystone/common/controller.py:18
+#, python-format
+msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
+msgstr ""
+
+#: keystone/common/controller.py:25
+msgid "RBAC: Invalid token"
+msgstr ""
+
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
+msgid "RBAC: Invalid user"
+msgstr ""
+
+#: keystone/common/controller.py:45
+msgid "RBAC: Proceeding without project"
+msgstr ""
+
+#: keystone/common/controller.py:65
+msgid "RBAC: Proceeding without tenant"
+msgstr ""
+
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
+msgid "RBAC: Bypassing authorization"
+msgstr ""
+
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
+msgid "RBAC: Authorization granted"
+msgstr ""
+
+#: keystone/common/controller.py:134
+#, python-format
+msgid "RBAC: Adding query filter params (%s)"
+msgstr ""
+
+#: keystone/common/controller.py:322
+msgid "Invalid token in normalize_domain_id"
+msgstr ""
+
+#: keystone/common/utils.py:233
+msgid ""
+"Error setting up the debug environment. Verify that the option --debug-"
+"url has the format <host>:<port> and that a debugger processes is "
+"listening on that port."
+msgstr ""
+
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
+#, python-format
+msgid "arg_dict: %s"
+msgstr ""
+
+#: keystone/common/wsgi.py:243
+#, python-format
+msgid "Authorization failed. %(exception)s from %(remote_addr)s"
+msgstr ""
+
+#: keystone/common/wsgi.py:487
+msgid "The resource could not be found."
+msgstr ""
+
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
+#, python-format
+msgid "Starting %(arg0)s on %(host)s:%(port)s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:113
+msgid "Server error"
+msgstr ""
+
+#: keystone/common/ldap/core.py:79
+#, python-format
+msgid "Invalid LDAP deref option: %s. Choose one of: "
+msgstr ""
+
+#: keystone/common/ldap/core.py:87
+#, python-format
+msgid "Invalid LDAP TLS certs option: %(option). Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:99
+#, python-format
+msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:189
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%s\". Format must be "
+"<ldap_attribute>:<keystone_attribute>"
+msgstr ""
+
+#: keystone/common/ldap/core.py:195
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%(item)s\". Value "
+"\"%(attr_map)s\" must use one of %(keys)s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
+#, python-format
+msgid "Duplicate name, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
+#, python-format
+msgid "Duplicate ID, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:294
+#, python-format
+msgid "LDAP %s create"
+msgstr ""
+
+#: keystone/common/ldap/core.py:372
+#, python-format
+msgid "LDAP %s update"
+msgstr ""
+
+#: keystone/common/ldap/core.py:405
+#, python-format
+msgid "LDAP %s delete"
+msgstr ""
+
+#: keystone/common/ldap/core.py:430
+#, python-format
+msgid "LDAP init: url=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:431
+#, python-format
+msgid ""
+"LDAP init: use_tls=%(use_tls)s\n"
+"tls_cacertfile=%(tls_cacertfile)s\n"
+"tls_cacertdir=%(tls_cacertdir)s\n"
+"tls_req_cert=%(tls_req_cert)s\n"
+"tls_avail=%(tls_avail)s\n"
+msgstr ""
+
+#: keystone/common/ldap/core.py:450
+msgid "Invalid TLS / LDAPS combination"
+msgstr ""
+
+#: keystone/common/ldap/core.py:454
+#, python-format
+msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available"
+msgstr ""
+
+#: keystone/common/ldap/core.py:464
+#, python-format
+msgid "tls_cacertfile %s not found or is not a file"
+msgstr ""
+
+#: keystone/common/ldap/core.py:476
+#, python-format
+msgid "tls_cacertdir %s not found or is not a directory"
+msgstr ""
+
+#: keystone/common/ldap/core.py:483
+#, python-format
+msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:497
+#, python-format
+msgid "LDAP bind: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:508
+#, python-format
+msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:514
+#, python-format
+msgid ""
+"LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, "
+"attrs=%(attrlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:567
+msgid ""
+"LDAP Server does not support paging. Disable paging in keystone.conf to "
+"avoid this message."
+msgstr ""
+
+#: keystone/common/ldap/core.py:584
+#, python-format
+msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:590
+#, python-format
+msgid "LDAP delete: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:595
+#, python-format
+msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:146
+#, python-format
+msgid "FakeLdap initialize url=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:156
+#, python-format
+msgid "FakeLdap bind dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:163
+#, python-format
+msgid "FakeLdap bind fail: dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:170
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:175
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s does not match"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:190
+#, python-format
+msgid "FakeLdap add item: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:193
+#, python-format
+msgid "FakeLdap add item failed: dn=%s is already in store."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:207 keystone/common/ldap/fakeldap.py:221
+#, python-format
+msgid "FakeLdap delete item: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:211 keystone/common/ldap/fakeldap.py:225
+#, python-format
+msgid "FakeLdap delete item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:240
+#, python-format
+msgid "FakeLdap modify item: dn=%(dn)s attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:245
+#, python-format
+msgid "FakeLdap modify item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:262
+#, python-format
+msgid "FakeLdap modify item failed: item has no attribute \"%s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:273
+#, python-format
+msgid ""
+"FakeLdap modify item failed: item has no attribute \"%(k)s\" with value "
+"\"%(v)s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:279
+#, python-format
+msgid "FakeLdap modify item failed: unknown command %s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:281
+#, python-format
+msgid "modify_s action %s not implemented"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:300
+#, python-format
+msgid "FakeLdap search at dn=%(dn)s scope=%(scope)s query=%(query)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:306
+msgid "FakeLdap search fail: dn not found for SCOPE_BASE"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:320
+#, python-format
+msgid "Search scope %s not implemented."
+msgstr ""
+
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
+#, python-format
+msgid "Got mysql server has gone away: %s"
+msgstr ""
+
+#: keystone/common/sql/legacy.py:188
+#, python-format
+msgid "Cannot migrate EC2 credential: %s"
+msgstr ""
+
+#: keystone/common/sql/migration.py:47
+msgid "version should be an integer"
+msgstr ""
+
+#: keystone/common/sql/nova.py:65
+#, python-format
+msgid "Create tenant %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:82
+#, python-format
+msgid "Create user %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:91
+#, python-format
+msgid "Add user %(user_id)s to tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:100
+#, python-format
+msgid "Ignoring existing role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:107
+#, python-format
+msgid "Create role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:117
+#, python-format
+msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:136
+#, python-format
+msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/identity/controllers.py:952
+#, python-format
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
+msgstr ""
+
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
+msgid "User not found in group"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:189
+#, python-format
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:334
+msgid "Changing Name not supported by LDAP"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:347
+#, python-format
+msgid "User %(user_id)s is already a member of group %(group_id)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:394
+#, python-format
+msgid "Failed to understand rule %(rule)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:404
+#, python-format
+msgid "No handler for matches of kind %s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:679
+#, python-format
+msgid "Failed to understand rule %(rule)r"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
+#: keystone/policy/backends/rules.py:93
+#, python-format
+msgid "enforce %(action)s: %(credentials)s"
+msgstr ""
+
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
+msgid "Token does not belong to specified tenant."
+msgstr ""
+
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
+msgstr ""
+
+#: keystone/token/backends/memcache.py:144
+#, python-format
+msgid ""
+"Successful set of token-index-list for user-key \"%(user_key)s\", "
+"#%(count)d records"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:154
+#, python-format
+msgid ""
+"Failed to set token-index-list for user-key \"%(user_key)s\". Attempt "
+"%(cas_retry)d of %(cas_retry_max)d"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:163
+msgid "Unable to add token user list"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:172
+msgid "Unable to add token to revocation list."
+msgstr ""
+
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
diff --git a/keystone/locale/hu/LC_MESSAGES/keystone.po b/keystone/locale/hu/LC_MESSAGES/keystone.po
index c6443004..c8942c5b 100644
--- a/keystone/locale/hu/LC_MESSAGES/keystone.po
+++ b/keystone/locale/hu/LC_MESSAGES/keystone.po
@@ -9,7 +9,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Keystone\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2013-06-17 17:09+0000\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
"PO-Revision-Date: 2012-12-15 14:14+0000\n"
"Last-Translator: kelemeng <kelemeng@gnome.hu>\n"
"Language-Team: hu <LL@li.org>\n"
@@ -17,7 +17,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.6\n"
+"Generated-By: Babel 1.3\n"
#: keystone/clean.py:23
#, python-format
@@ -39,63 +39,224 @@ msgstr "%(property_name)s nem lehet több, mint %(max_length)s karakter."
msgid "%(property_name)s is not a %(display_expected_type)s"
msgstr "%(property_name)s nem %(display_expected_type)s"
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
#: keystone/test.py:117
#, python-format
msgid "Failed to checkout %s"
msgstr "Nem sikerült %s kiiktatása"
-#: keystone/auth/controllers.py:72
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr ""
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr ""
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
#, python-format
msgid "Project is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:78 keystone/auth/plugins/password.py:39
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
#, python-format
msgid "Domain is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:84 keystone/auth/plugins/password.py:45
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
#, python-format
msgid "User is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:265
+#: keystone/auth/controllers.py:262
msgid "Scoping to both domain and project is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:268
+#: keystone/auth/controllers.py:265
msgid "Scoping to both domain and trust is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:271
+#: keystone/auth/controllers.py:268
msgid "Scoping to both project and trust is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:333
-#, fuzzy, python-format
-msgid "Unable to lookup user %s"
-msgstr "Nem vehető fel a token felhasználólistája."
-
-#: keystone/auth/controllers.py:363
+#: keystone/auth/controllers.py:353
msgid "User not found"
msgstr ""
-#: keystone/auth/token_factory.py:81
-msgid "User have no access to project"
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
msgstr ""
-#: keystone/auth/token_factory.py:96
-msgid "User have no access to domain"
-msgstr ""
-
-#: keystone/auth/token_factory.py:314 keystone/token/controllers.py:121
-#, fuzzy
-msgid "Unable to sign token."
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
+#, fuzzy, python-format
+msgid "Unable to lookup user %s"
msgstr "Nem vehető fel a token felhasználólistája."
-#: keystone/auth/token_factory.py:317 keystone/token/controllers.py:124
-#, python-format
-msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
msgstr ""
#: keystone/catalog/core.py:38
@@ -124,18 +285,18 @@ msgstr "Rosszul formázott végpont: %s hiányos formátum (hiányzik egy típus
msgid "Unable to open template file %s"
msgstr "Nem nyitható meg a sablonfájl: %s"
-#: keystone/common/cms.py:42
+#: keystone/common/cms.py:26
#, python-format
msgid "Verify error: %s"
msgstr "Ellenőrzési hiba: %s"
-#: keystone/common/cms.py:134
+#: keystone/common/cms.py:118
msgid ""
"Signing error: Unable to load certificate - ensure you've configured PKI "
"with 'keystone-manage pki_setup'"
msgstr ""
-#: keystone/common/cms.py:138
+#: keystone/common/cms.py:122
#, python-format
msgid "Signing error: %s"
msgstr "Aláírási hiba: %s"
@@ -154,31 +315,31 @@ msgstr "Érvénytelen rendszernapló szolgáltatás"
msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
msgstr ""
-#: keystone/common/controller.py:26
+#: keystone/common/controller.py:25
msgid "RBAC: Invalid token"
msgstr ""
-#: keystone/common/controller.py:36 keystone/common/controller.py:57
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
msgid "RBAC: Invalid user"
msgstr ""
-#: keystone/common/controller.py:42
+#: keystone/common/controller.py:45
msgid "RBAC: Proceeding without project"
msgstr ""
-#: keystone/common/controller.py:62
+#: keystone/common/controller.py:65
msgid "RBAC: Proceeding without tenant"
msgstr ""
-#: keystone/common/controller.py:92 keystone/common/controller.py:144
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
msgid "RBAC: Bypassing authorization"
msgstr ""
-#: keystone/common/controller.py:101 keystone/common/controller.py:142
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
msgid "RBAC: Authorization granted"
msgstr ""
-#: keystone/common/controller.py:131
+#: keystone/common/controller.py:134
#, python-format
msgid "RBAC: Adding query filter params (%s)"
msgstr ""
@@ -187,33 +348,69 @@ msgstr ""
msgid "Invalid token in normalize_domain_id"
msgstr ""
-#: keystone/common/utils.py:232
+#: keystone/common/utils.py:233
msgid ""
"Error setting up the debug environment. Verify that the option --debug-"
"url has the format <host>:<port> and that a debugger processes is "
"listening on that port."
msgstr ""
-#: keystone/common/wsgi.py:162
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
#, python-format
msgid "arg_dict: %s"
msgstr "arg_dict: %s"
-#: keystone/common/wsgi.py:186
+#: keystone/common/wsgi.py:243
#, fuzzy, python-format
msgid "Authorization failed. %(exception)s from %(remote_addr)s"
msgstr "Hitelesítés sikertelen. %s innen: %s"
-#: keystone/common/wsgi.py:429
+#: keystone/common/wsgi.py:487
msgid "The resource could not be found."
msgstr "Az erőforrás nem található."
-#: keystone/common/wsgi_server.py:72
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
#, python-format
msgid "Starting %(arg0)s on %(host)s:%(port)s"
msgstr "%(arg0)s indítása ezen: %(host)s:%(port)s"
-#: keystone/common/wsgi_server.py:132
+#: keystone/common/environment/eventlet_server.py:113
msgid "Server error"
msgstr ""
@@ -246,13 +443,13 @@ msgid ""
"\"%(attr_map)s\" must use one of %(keys)s."
msgstr ""
-#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:596
-#: keystone/identity/backends/kvs.py:624
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
#, python-format
msgid "Duplicate name, %s."
msgstr "Többszörös név: %s."
-#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:589
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
#, python-format
msgid "Duplicate ID, %s."
msgstr "Többszörös azonosító: %s."
@@ -444,12 +641,16 @@ msgstr "FakeLdap keresés sikertelen: a dn nem található a SCOPE_BASE-hez"
msgid "Search scope %s not implemented."
msgstr "A(z) %s keresési hatókör nincs megvalósítva."
-#: keystone/common/sql/core.py:205
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
#, python-format
msgid "Got mysql server has gone away: %s"
msgstr "A kapott MySQL szerver eltűnt: %s"
-#: keystone/common/sql/legacy.py:180
+#: keystone/common/sql/legacy.py:188
#, python-format
msgid "Cannot migrate EC2 credential: %s"
msgstr "Nem migrálhatók az EC2 hitelesítési adatok: %s"
@@ -458,76 +659,68 @@ msgstr "Nem migrálhatók az EC2 hitelesítési adatok: %s"
msgid "version should be an integer"
msgstr ""
-#: keystone/common/sql/nova.py:62
+#: keystone/common/sql/nova.py:65
#, python-format
msgid "Create tenant %s"
msgstr "%s bérlő létrehozása"
-#: keystone/common/sql/nova.py:79
+#: keystone/common/sql/nova.py:82
#, python-format
msgid "Create user %s"
msgstr "%s felhasználó létrehozása"
-#: keystone/common/sql/nova.py:88
+#: keystone/common/sql/nova.py:91
#, fuzzy, python-format
msgid "Add user %(user_id)s to tenant %(tenant_id)s"
msgstr "%s felhasználó hozzáadása %s bérlőhöz"
-#: keystone/common/sql/nova.py:97
+#: keystone/common/sql/nova.py:100
#, python-format
msgid "Ignoring existing role %s"
msgstr "Meglévő %s szerep figyelmen kívül hagyása"
-#: keystone/common/sql/nova.py:104
+#: keystone/common/sql/nova.py:107
#, python-format
msgid "Create role %s"
msgstr "%s szerep létrehozása"
-#: keystone/common/sql/nova.py:114
+#: keystone/common/sql/nova.py:117
#, fuzzy, python-format
msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
msgstr "%s szerep hozzárendelése %s felhasználóhoz %s bérlőben"
-#: keystone/common/sql/nova.py:133
+#: keystone/common/sql/nova.py:136
#, fuzzy, python-format
msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
msgstr "EC2 hitelesítési adatok létrehozása %s felhasználóhoz és %s bérlőhöz"
-#: keystone/identity/backends/kvs.py:250 keystone/identity/backends/kvs.py:259
-msgid "User not found in group"
-msgstr ""
-
-#: keystone/identity/backends/sql.py:425
+#: keystone/identity/controllers.py:952
#, python-format
-msgid "Cannot remove role that has not been granted, %s"
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:82
-#, python-format
-msgid "Expected dict or list: %s"
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
+msgid "User not found in group"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:681
+#: keystone/identity/backends/ldap.py:189
#, python-format
-msgid "Role %s not found"
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
msgstr ""
-#: keystone/identity/backends/ldap/core.py:898
+#: keystone/identity/backends/ldap.py:334
msgid "Changing Name not supported by LDAP"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:911
+#: keystone/identity/backends/ldap.py:347
#, python-format
msgid "User %(user_id)s is already a member of group %(group_id)s"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:954
-#, python-format
-msgid ""
-"Group member '%(user_dn)s' not found in '%(group_dn)s'. The user should "
-"be removed from the group. The user will be ignored."
-msgstr ""
-
#: keystone/openstack/common/policy.py:394
#, python-format
msgid "Failed to understand rule %(rule)s"
@@ -543,21 +736,56 @@ msgstr ""
msgid "Failed to understand rule %(rule)r"
msgstr ""
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
#: keystone/policy/backends/rules.py:93
#, python-format
msgid "enforce %(action)s: %(credentials)s"
msgstr ""
-#: keystone/token/controllers.py:465 keystone/token/controllers.py:468
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
msgid "Token does not belong to specified tenant."
msgstr ""
-#: keystone/token/controllers.py:475
-msgid "Non-default domain is not supported"
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
msgstr ""
-#: keystone/token/controllers.py:483
-msgid "Domain scoped token is not supported"
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
msgstr ""
#: keystone/token/backends/memcache.py:144
@@ -582,3 +810,55 @@ msgstr ""
msgid "Unable to add token to revocation list."
msgstr "A token nem adható a visszavonási listához."
+#: keystone/token/providers/pki.py:43
+#, fuzzy
+msgid "Unable to sign token."
+msgstr "Nem vehető fel a token felhasználólistája."
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
+#~ msgid "User have no access to project"
+#~ msgstr ""
+
+#~ msgid "User have no access to domain"
+#~ msgstr ""
+
+#~ msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+#~ msgstr ""
+
diff --git a/keystone/locale/id/LC_MESSAGES/keystone.po b/keystone/locale/id/LC_MESSAGES/keystone.po
new file mode 100644
index 00000000..1d5650b6
--- /dev/null
+++ b/keystone/locale/id/LC_MESSAGES/keystone.po
@@ -0,0 +1,847 @@
+# Indonesian translations for keystone.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the keystone project.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: Keystone\n"
+"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
+"PO-Revision-Date: 2013-07-29 22:01+0000\n"
+"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
+"Language-Team: Indonesian "
+"(http://www.transifex.com/projects/p/openstack/language/id/)\n"
+"Plural-Forms: nplurals=1; plural=0\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: keystone/clean.py:23
+#, python-format
+msgid "%s cannot be empty."
+msgstr ""
+
+#: keystone/clean.py:25
+#, python-format
+msgid "%(property_name)s cannot be less than %(min_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:29
+#, python-format
+msgid "%(property_name)s should not be greater than %(max_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:36
+#, python-format
+msgid "%(property_name)s is not a %(display_expected_type)s"
+msgstr ""
+
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
+#: keystone/test.py:117
+#, python-format
+msgid "Failed to checkout %s"
+msgstr ""
+
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr ""
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr ""
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
+#, python-format
+msgid "Project is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
+#, python-format
+msgid "Domain is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
+#, python-format
+msgid "User is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:262
+msgid "Scoping to both domain and project is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:265
+msgid "Scoping to both domain and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:268
+msgid "Scoping to both project and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:353
+msgid "User not found"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
+#, python-format
+msgid "Unable to lookup user %s"
+msgstr ""
+
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
+msgstr ""
+
+#: keystone/catalog/core.py:38
+#, python-format
+msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s"
+msgstr ""
+
+#: keystone/catalog/core.py:43
+#, python-format
+msgid ""
+"Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing "
+"brackets ?)"
+msgstr ""
+
+#: keystone/catalog/core.py:49
+#, python-format
+msgid ""
+"Malformed endpoint %s - incomplete format (are you "
+"missing a type notifier ?)"
+msgstr ""
+
+#: keystone/catalog/backends/templated.py:109
+#, python-format
+msgid "Unable to open template file %s"
+msgstr ""
+
+#: keystone/common/cms.py:26
+#, python-format
+msgid "Verify error: %s"
+msgstr ""
+
+#: keystone/common/cms.py:118
+msgid ""
+"Signing error: Unable to load certificate - ensure you've configured PKI "
+"with 'keystone-manage pki_setup'"
+msgstr ""
+
+#: keystone/common/cms.py:122
+#, python-format
+msgid "Signing error: %s"
+msgstr ""
+
+#: keystone/common/config.py:89
+#, python-format
+msgid "Unable to locate specified logging config file: %s"
+msgstr ""
+
+#: keystone/common/config.py:107
+msgid "Invalid syslog facility"
+msgstr ""
+
+#: keystone/common/controller.py:18
+#, python-format
+msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
+msgstr ""
+
+#: keystone/common/controller.py:25
+msgid "RBAC: Invalid token"
+msgstr ""
+
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
+msgid "RBAC: Invalid user"
+msgstr ""
+
+#: keystone/common/controller.py:45
+msgid "RBAC: Proceeding without project"
+msgstr ""
+
+#: keystone/common/controller.py:65
+msgid "RBAC: Proceeding without tenant"
+msgstr ""
+
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
+msgid "RBAC: Bypassing authorization"
+msgstr ""
+
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
+msgid "RBAC: Authorization granted"
+msgstr ""
+
+#: keystone/common/controller.py:134
+#, python-format
+msgid "RBAC: Adding query filter params (%s)"
+msgstr ""
+
+#: keystone/common/controller.py:322
+msgid "Invalid token in normalize_domain_id"
+msgstr ""
+
+#: keystone/common/utils.py:233
+msgid ""
+"Error setting up the debug environment. Verify that the option --debug-"
+"url has the format <host>:<port> and that a debugger processes is "
+"listening on that port."
+msgstr ""
+
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
+#, python-format
+msgid "arg_dict: %s"
+msgstr ""
+
+#: keystone/common/wsgi.py:243
+#, python-format
+msgid "Authorization failed. %(exception)s from %(remote_addr)s"
+msgstr ""
+
+#: keystone/common/wsgi.py:487
+msgid "The resource could not be found."
+msgstr ""
+
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
+#, python-format
+msgid "Starting %(arg0)s on %(host)s:%(port)s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:113
+msgid "Server error"
+msgstr ""
+
+#: keystone/common/ldap/core.py:79
+#, python-format
+msgid "Invalid LDAP deref option: %s. Choose one of: "
+msgstr ""
+
+#: keystone/common/ldap/core.py:87
+#, python-format
+msgid "Invalid LDAP TLS certs option: %(option). Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:99
+#, python-format
+msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:189
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%s\". Format must be "
+"<ldap_attribute>:<keystone_attribute>"
+msgstr ""
+
+#: keystone/common/ldap/core.py:195
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%(item)s\". Value "
+"\"%(attr_map)s\" must use one of %(keys)s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
+#, python-format
+msgid "Duplicate name, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
+#, python-format
+msgid "Duplicate ID, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:294
+#, python-format
+msgid "LDAP %s create"
+msgstr ""
+
+#: keystone/common/ldap/core.py:372
+#, python-format
+msgid "LDAP %s update"
+msgstr ""
+
+#: keystone/common/ldap/core.py:405
+#, python-format
+msgid "LDAP %s delete"
+msgstr ""
+
+#: keystone/common/ldap/core.py:430
+#, python-format
+msgid "LDAP init: url=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:431
+#, python-format
+msgid ""
+"LDAP init: use_tls=%(use_tls)s\n"
+"tls_cacertfile=%(tls_cacertfile)s\n"
+"tls_cacertdir=%(tls_cacertdir)s\n"
+"tls_req_cert=%(tls_req_cert)s\n"
+"tls_avail=%(tls_avail)s\n"
+msgstr ""
+
+#: keystone/common/ldap/core.py:450
+msgid "Invalid TLS / LDAPS combination"
+msgstr ""
+
+#: keystone/common/ldap/core.py:454
+#, python-format
+msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available"
+msgstr ""
+
+#: keystone/common/ldap/core.py:464
+#, python-format
+msgid "tls_cacertfile %s not found or is not a file"
+msgstr ""
+
+#: keystone/common/ldap/core.py:476
+#, python-format
+msgid "tls_cacertdir %s not found or is not a directory"
+msgstr ""
+
+#: keystone/common/ldap/core.py:483
+#, python-format
+msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:497
+#, python-format
+msgid "LDAP bind: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:508
+#, python-format
+msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:514
+#, python-format
+msgid ""
+"LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, "
+"attrs=%(attrlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:567
+msgid ""
+"LDAP Server does not support paging. Disable paging in keystone.conf to "
+"avoid this message."
+msgstr ""
+
+#: keystone/common/ldap/core.py:584
+#, python-format
+msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:590
+#, python-format
+msgid "LDAP delete: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:595
+#, python-format
+msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:146
+#, python-format
+msgid "FakeLdap initialize url=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:156
+#, python-format
+msgid "FakeLdap bind dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:163
+#, python-format
+msgid "FakeLdap bind fail: dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:170
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:175
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s does not match"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:190
+#, python-format
+msgid "FakeLdap add item: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:193
+#, python-format
+msgid "FakeLdap add item failed: dn=%s is already in store."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:207 keystone/common/ldap/fakeldap.py:221
+#, python-format
+msgid "FakeLdap delete item: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:211 keystone/common/ldap/fakeldap.py:225
+#, python-format
+msgid "FakeLdap delete item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:240
+#, python-format
+msgid "FakeLdap modify item: dn=%(dn)s attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:245
+#, python-format
+msgid "FakeLdap modify item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:262
+#, python-format
+msgid "FakeLdap modify item failed: item has no attribute \"%s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:273
+#, python-format
+msgid ""
+"FakeLdap modify item failed: item has no attribute \"%(k)s\" with value "
+"\"%(v)s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:279
+#, python-format
+msgid "FakeLdap modify item failed: unknown command %s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:281
+#, python-format
+msgid "modify_s action %s not implemented"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:300
+#, python-format
+msgid "FakeLdap search at dn=%(dn)s scope=%(scope)s query=%(query)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:306
+msgid "FakeLdap search fail: dn not found for SCOPE_BASE"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:320
+#, python-format
+msgid "Search scope %s not implemented."
+msgstr ""
+
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
+#, python-format
+msgid "Got mysql server has gone away: %s"
+msgstr ""
+
+#: keystone/common/sql/legacy.py:188
+#, python-format
+msgid "Cannot migrate EC2 credential: %s"
+msgstr ""
+
+#: keystone/common/sql/migration.py:47
+msgid "version should be an integer"
+msgstr ""
+
+#: keystone/common/sql/nova.py:65
+#, python-format
+msgid "Create tenant %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:82
+#, python-format
+msgid "Create user %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:91
+#, python-format
+msgid "Add user %(user_id)s to tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:100
+#, python-format
+msgid "Ignoring existing role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:107
+#, python-format
+msgid "Create role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:117
+#, python-format
+msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:136
+#, python-format
+msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/identity/controllers.py:952
+#, python-format
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
+msgstr ""
+
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
+msgid "User not found in group"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:189
+#, python-format
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:334
+msgid "Changing Name not supported by LDAP"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:347
+#, python-format
+msgid "User %(user_id)s is already a member of group %(group_id)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:394
+#, python-format
+msgid "Failed to understand rule %(rule)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:404
+#, python-format
+msgid "No handler for matches of kind %s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:679
+#, python-format
+msgid "Failed to understand rule %(rule)r"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
+#: keystone/policy/backends/rules.py:93
+#, python-format
+msgid "enforce %(action)s: %(credentials)s"
+msgstr ""
+
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
+msgid "Token does not belong to specified tenant."
+msgstr ""
+
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
+msgstr ""
+
+#: keystone/token/backends/memcache.py:144
+#, python-format
+msgid ""
+"Successful set of token-index-list for user-key \"%(user_key)s\", "
+"#%(count)d records"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:154
+#, python-format
+msgid ""
+"Failed to set token-index-list for user-key \"%(user_key)s\". Attempt "
+"%(cas_retry)d of %(cas_retry_max)d"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:163
+msgid "Unable to add token user list"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:172
+msgid "Unable to add token to revocation list."
+msgstr ""
+
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
diff --git a/keystone/locale/it/LC_MESSAGES/keystone.po b/keystone/locale/it/LC_MESSAGES/keystone.po
index 7f3d7280..89f965ee 100644
--- a/keystone/locale/it/LC_MESSAGES/keystone.po
+++ b/keystone/locale/it/LC_MESSAGES/keystone.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Keystone\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2013-06-17 17:09+0000\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
"PO-Revision-Date: 2013-05-17 16:06+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
"Language-Team: Italian "
@@ -16,7 +16,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.6\n"
+"Generated-By: Babel 1.3\n"
#: keystone/clean.py:23
#, python-format
@@ -38,65 +38,225 @@ msgstr "%(property_name)s non può essere superiore a %(max_length)s caratteri."
msgid "%(property_name)s is not a %(display_expected_type)s"
msgstr ""
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
#: keystone/test.py:117
#, python-format
msgid "Failed to checkout %s"
msgstr "Impossibile eseguire il checkout %s"
-#: keystone/auth/controllers.py:72
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr "Impossibile rimuovere un ruolo che non è stato concesso, %s"
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr "Ruolo %s non trovato"
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
#, python-format
msgid "Project is disabled: %s"
msgstr "Il progetto è disabilitato: %s"
-#: keystone/auth/controllers.py:78 keystone/auth/plugins/password.py:39
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
#, python-format
msgid "Domain is disabled: %s"
msgstr "Il dominio è disabilitato: %s"
-#: keystone/auth/controllers.py:84 keystone/auth/plugins/password.py:45
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
#, python-format
msgid "User is disabled: %s"
msgstr "L'utente è disabilitato: %s"
-#: keystone/auth/controllers.py:265
+#: keystone/auth/controllers.py:262
msgid "Scoping to both domain and project is not allowed"
msgstr "Il controllo sia del dominio che del progetto non è consentito"
-#: keystone/auth/controllers.py:268
+#: keystone/auth/controllers.py:265
msgid "Scoping to both domain and trust is not allowed"
msgstr "Il controllo sia del dominio che di trust non è consentito"
-#: keystone/auth/controllers.py:271
+#: keystone/auth/controllers.py:268
msgid "Scoping to both project and trust is not allowed"
msgstr "Il controllo sia delprogetto che di trust non è consentito"
-#: keystone/auth/controllers.py:333
-#, python-format
-msgid "Unable to lookup user %s"
-msgstr "Impossibile eseguire la ricerca dell'utente %s"
-
-#: keystone/auth/controllers.py:363
+#: keystone/auth/controllers.py:353
msgid "User not found"
msgstr "Utente non trovato"
-#: keystone/auth/token_factory.py:81
-msgid "User have no access to project"
-msgstr "L'utente non ha accesso al progetto"
-
-#: keystone/auth/token_factory.py:96
-msgid "User have no access to domain"
-msgstr "L'utente non ha accesso al dominio"
-
-#: keystone/auth/token_factory.py:314 keystone/token/controllers.py:121
-msgid "Unable to sign token."
-msgstr "Impossibile firmare il token."
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
+msgstr ""
-#: keystone/auth/token_factory.py:317 keystone/token/controllers.py:124
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
#, python-format
-msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+msgid "Unable to lookup user %s"
+msgstr "Impossibile eseguire la ricerca dell'utente %s"
+
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
msgstr ""
-"Valore non valido per token_format: %s. I valori consentiti sono PKI o "
-"UUID."
#: keystone/catalog/core.py:38
#, python-format
@@ -126,12 +286,12 @@ msgstr ""
msgid "Unable to open template file %s"
msgstr "Impossibile aprire il file di template %s"
-#: keystone/common/cms.py:42
+#: keystone/common/cms.py:26
#, python-format
msgid "Verify error: %s"
msgstr "Verifica errore: %s"
-#: keystone/common/cms.py:134
+#: keystone/common/cms.py:118
msgid ""
"Signing error: Unable to load certificate - ensure you've configured PKI "
"with 'keystone-manage pki_setup'"
@@ -139,7 +299,7 @@ msgstr ""
"errore di firma: impossibile caricare il certificato - assicurarsi che "
"sia stato configurato PKI con 'keystone-manage pki_setup'"
-#: keystone/common/cms.py:138
+#: keystone/common/cms.py:122
#, python-format
msgid "Signing error: %s"
msgstr "Errore di firma: %s"
@@ -158,31 +318,31 @@ msgstr "Funzione syslog non valida"
msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
msgstr ""
-#: keystone/common/controller.py:26
+#: keystone/common/controller.py:25
msgid "RBAC: Invalid token"
msgstr "RBAC: token non valido"
-#: keystone/common/controller.py:36 keystone/common/controller.py:57
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
msgid "RBAC: Invalid user"
msgstr "RBAC: utente non valido"
-#: keystone/common/controller.py:42
+#: keystone/common/controller.py:45
msgid "RBAC: Proceeding without project"
msgstr "RBAC: si procede senza progetto"
-#: keystone/common/controller.py:62
+#: keystone/common/controller.py:65
msgid "RBAC: Proceeding without tenant"
msgstr "RBAC: si procede senza tenant"
-#: keystone/common/controller.py:92 keystone/common/controller.py:144
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
msgid "RBAC: Bypassing authorization"
msgstr "RBAC: autorizzazione oltrepassata"
-#: keystone/common/controller.py:101 keystone/common/controller.py:142
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
msgid "RBAC: Authorization granted"
msgstr "RBAC: autorizzazione concessa"
-#: keystone/common/controller.py:131
+#: keystone/common/controller.py:134
#, python-format
msgid "RBAC: Adding query filter params (%s)"
msgstr "RBAC: aggiunta parametri del filtro della query (%s)"
@@ -191,33 +351,69 @@ msgstr "RBAC: aggiunta parametri del filtro della query (%s)"
msgid "Invalid token in normalize_domain_id"
msgstr "Token non valido in normalize_domain_id"
-#: keystone/common/utils.py:232
+#: keystone/common/utils.py:233
msgid ""
"Error setting up the debug environment. Verify that the option --debug-"
"url has the format <host>:<port> and that a debugger processes is "
"listening on that port."
msgstr ""
-#: keystone/common/wsgi.py:162
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
#, python-format
msgid "arg_dict: %s"
msgstr "arg_dict: %s"
-#: keystone/common/wsgi.py:186
+#: keystone/common/wsgi.py:243
#, fuzzy, python-format
msgid "Authorization failed. %(exception)s from %(remote_addr)s"
msgstr "Autorizzazione non riuscita. %s da %s"
-#: keystone/common/wsgi.py:429
+#: keystone/common/wsgi.py:487
msgid "The resource could not be found."
msgstr "Impossibile trovare la risorsa."
-#: keystone/common/wsgi_server.py:72
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
#, python-format
msgid "Starting %(arg0)s on %(host)s:%(port)s"
msgstr "Avvio %(arg0)s in %(host)s:%(port)s"
-#: keystone/common/wsgi_server.py:132
+#: keystone/common/environment/eventlet_server.py:113
msgid "Server error"
msgstr "Errore del server"
@@ -250,13 +446,13 @@ msgid ""
"\"%(attr_map)s\" must use one of %(keys)s."
msgstr ""
-#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:596
-#: keystone/identity/backends/kvs.py:624
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
#, python-format
msgid "Duplicate name, %s."
msgstr "Nome duplicato, %s."
-#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:589
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
#, python-format
msgid "Duplicate ID, %s."
msgstr "ID duplicato, %s."
@@ -450,12 +646,16 @@ msgstr "FakeLdap ricerca non riuscita: dn non trovato per SCOPE_BASE"
msgid "Search scope %s not implemented."
msgstr "Ambito di ricerca %s non implementato."
-#: keystone/common/sql/core.py:205
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
#, python-format
msgid "Got mysql server has gone away: %s"
msgstr "Ricevuto messaggio di interruzione della connessione del server mysql: %s"
-#: keystone/common/sql/legacy.py:180
+#: keystone/common/sql/legacy.py:188
#, python-format
msgid "Cannot migrate EC2 credential: %s"
msgstr "Impossibile migrare la credenziale EC2: %s"
@@ -464,76 +664,68 @@ msgstr "Impossibile migrare la credenziale EC2: %s"
msgid "version should be an integer"
msgstr "la versione deve essere un numero intero"
-#: keystone/common/sql/nova.py:62
+#: keystone/common/sql/nova.py:65
#, python-format
msgid "Create tenant %s"
msgstr "Crea tenant %s"
-#: keystone/common/sql/nova.py:79
+#: keystone/common/sql/nova.py:82
#, python-format
msgid "Create user %s"
msgstr "Crea utente %s"
-#: keystone/common/sql/nova.py:88
+#: keystone/common/sql/nova.py:91
#, fuzzy, python-format
msgid "Add user %(user_id)s to tenant %(tenant_id)s"
msgstr "Aggiungi utente %s al tenant %s"
-#: keystone/common/sql/nova.py:97
+#: keystone/common/sql/nova.py:100
#, python-format
msgid "Ignoring existing role %s"
msgstr "Il ruolo esistente viene ignorato %s"
-#: keystone/common/sql/nova.py:104
+#: keystone/common/sql/nova.py:107
#, python-format
msgid "Create role %s"
msgstr "Crea ruolo %s"
-#: keystone/common/sql/nova.py:114
+#: keystone/common/sql/nova.py:117
#, fuzzy, python-format
msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
msgstr "Assegna il ruolo %s all'utente %s nel tenant %s"
-#: keystone/common/sql/nova.py:133
+#: keystone/common/sql/nova.py:136
#, fuzzy, python-format
msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
msgstr "Creazione credenziale ec2 per l'utente %s e del tenant %s"
-#: keystone/identity/backends/kvs.py:250 keystone/identity/backends/kvs.py:259
+#: keystone/identity/controllers.py:952
+#, python-format
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
+msgstr ""
+
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
msgid "User not found in group"
msgstr "Utente non trovato nel gruppo"
-#: keystone/identity/backends/sql.py:425
-#, python-format
-msgid "Cannot remove role that has not been granted, %s"
-msgstr "Impossibile rimuovere un ruolo che non è stato concesso, %s"
-
-#: keystone/identity/backends/ldap/core.py:82
+#: keystone/identity/backends/ldap.py:189
#, python-format
-msgid "Expected dict or list: %s"
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
msgstr ""
-#: keystone/identity/backends/ldap/core.py:681
-#, python-format
-msgid "Role %s not found"
-msgstr "Ruolo %s non trovato"
-
-#: keystone/identity/backends/ldap/core.py:898
+#: keystone/identity/backends/ldap.py:334
msgid "Changing Name not supported by LDAP"
msgstr "Modifica nome non supportato da LDAP"
-#: keystone/identity/backends/ldap/core.py:911
+#: keystone/identity/backends/ldap.py:347
#, fuzzy, python-format
msgid "User %(user_id)s is already a member of group %(group_id)s"
msgstr "L'utente %s è già membro del gruppo %s"
-#: keystone/identity/backends/ldap/core.py:954
-#, python-format
-msgid ""
-"Group member '%(user_dn)s' not found in '%(group_dn)s'. The user should "
-"be removed from the group. The user will be ignored."
-msgstr ""
-
#: keystone/openstack/common/policy.py:394
#, python-format
msgid "Failed to understand rule %(rule)s"
@@ -549,22 +741,57 @@ msgstr "Nessun gestore per le corrispondenze di tipo %s"
msgid "Failed to understand rule %(rule)r"
msgstr "Impossibile comprendere la regola %(rule)r"
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
#: keystone/policy/backends/rules.py:93
#, python-format
msgid "enforce %(action)s: %(credentials)s"
msgstr ""
-#: keystone/token/controllers.py:465 keystone/token/controllers.py:468
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
msgid "Token does not belong to specified tenant."
msgstr "Il token non appartiene al tenant specificato."
-#: keystone/token/controllers.py:475
-msgid "Non-default domain is not supported"
-msgstr "Il dominio non predefinito non è supportato"
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
+msgstr ""
-#: keystone/token/controllers.py:483
-msgid "Domain scoped token is not supported"
-msgstr "L'ambito del dominio token non è supportato"
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
+msgstr ""
#: keystone/token/backends/memcache.py:144
#, python-format
@@ -588,3 +815,57 @@ msgstr ""
msgid "Unable to add token to revocation list."
msgstr "Impossibile aggiungere un token ad un elenco di revoca."
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr "Impossibile firmare il token."
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr "Il dominio non predefinito non è supportato"
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr "L'ambito del dominio token non è supportato"
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
+#~ msgid "User have no access to project"
+#~ msgstr "L'utente non ha accesso al progetto"
+
+#~ msgid "User have no access to domain"
+#~ msgstr "L'utente non ha accesso al dominio"
+
+#~ msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+#~ msgstr ""
+#~ "Valore non valido per token_format: %s."
+#~ " I valori consentiti sono PKI o "
+#~ "UUID."
+
diff --git a/keystone/locale/it_IT/LC_MESSAGES/keystone.po b/keystone/locale/it_IT/LC_MESSAGES/keystone.po
new file mode 100644
index 00000000..7b8e76da
--- /dev/null
+++ b/keystone/locale/it_IT/LC_MESSAGES/keystone.po
@@ -0,0 +1,847 @@
+# Italian (Italy) translations for keystone.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the keystone project.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: Keystone\n"
+"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
+"PO-Revision-Date: 2013-07-29 22:01+0000\n"
+"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
+"Language-Team: Italian (Italy) "
+"(http://www.transifex.com/projects/p/openstack/language/it_IT/)\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: keystone/clean.py:23
+#, python-format
+msgid "%s cannot be empty."
+msgstr ""
+
+#: keystone/clean.py:25
+#, python-format
+msgid "%(property_name)s cannot be less than %(min_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:29
+#, python-format
+msgid "%(property_name)s should not be greater than %(max_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:36
+#, python-format
+msgid "%(property_name)s is not a %(display_expected_type)s"
+msgstr ""
+
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
+#: keystone/test.py:117
+#, python-format
+msgid "Failed to checkout %s"
+msgstr ""
+
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr ""
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr ""
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
+#, python-format
+msgid "Project is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
+#, python-format
+msgid "Domain is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
+#, python-format
+msgid "User is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:262
+msgid "Scoping to both domain and project is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:265
+msgid "Scoping to both domain and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:268
+msgid "Scoping to both project and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:353
+msgid "User not found"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
+#, python-format
+msgid "Unable to lookup user %s"
+msgstr ""
+
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
+msgstr ""
+
+#: keystone/catalog/core.py:38
+#, python-format
+msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s"
+msgstr ""
+
+#: keystone/catalog/core.py:43
+#, python-format
+msgid ""
+"Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing "
+"brackets ?)"
+msgstr ""
+
+#: keystone/catalog/core.py:49
+#, python-format
+msgid ""
+"Malformed endpoint %s - incomplete format (are you "
+"missing a type notifier ?)"
+msgstr ""
+
+#: keystone/catalog/backends/templated.py:109
+#, python-format
+msgid "Unable to open template file %s"
+msgstr ""
+
+#: keystone/common/cms.py:26
+#, python-format
+msgid "Verify error: %s"
+msgstr ""
+
+#: keystone/common/cms.py:118
+msgid ""
+"Signing error: Unable to load certificate - ensure you've configured PKI "
+"with 'keystone-manage pki_setup'"
+msgstr ""
+
+#: keystone/common/cms.py:122
+#, python-format
+msgid "Signing error: %s"
+msgstr ""
+
+#: keystone/common/config.py:89
+#, python-format
+msgid "Unable to locate specified logging config file: %s"
+msgstr ""
+
+#: keystone/common/config.py:107
+msgid "Invalid syslog facility"
+msgstr ""
+
+#: keystone/common/controller.py:18
+#, python-format
+msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
+msgstr ""
+
+#: keystone/common/controller.py:25
+msgid "RBAC: Invalid token"
+msgstr ""
+
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
+msgid "RBAC: Invalid user"
+msgstr ""
+
+#: keystone/common/controller.py:45
+msgid "RBAC: Proceeding without project"
+msgstr ""
+
+#: keystone/common/controller.py:65
+msgid "RBAC: Proceeding without tenant"
+msgstr ""
+
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
+msgid "RBAC: Bypassing authorization"
+msgstr ""
+
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
+msgid "RBAC: Authorization granted"
+msgstr ""
+
+#: keystone/common/controller.py:134
+#, python-format
+msgid "RBAC: Adding query filter params (%s)"
+msgstr ""
+
+#: keystone/common/controller.py:322
+msgid "Invalid token in normalize_domain_id"
+msgstr ""
+
+#: keystone/common/utils.py:233
+msgid ""
+"Error setting up the debug environment. Verify that the option --debug-"
+"url has the format <host>:<port> and that a debugger processes is "
+"listening on that port."
+msgstr ""
+
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
+#, python-format
+msgid "arg_dict: %s"
+msgstr ""
+
+#: keystone/common/wsgi.py:243
+#, python-format
+msgid "Authorization failed. %(exception)s from %(remote_addr)s"
+msgstr ""
+
+#: keystone/common/wsgi.py:487
+msgid "The resource could not be found."
+msgstr ""
+
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
+#, python-format
+msgid "Starting %(arg0)s on %(host)s:%(port)s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:113
+msgid "Server error"
+msgstr ""
+
+#: keystone/common/ldap/core.py:79
+#, python-format
+msgid "Invalid LDAP deref option: %s. Choose one of: "
+msgstr ""
+
+#: keystone/common/ldap/core.py:87
+#, python-format
+msgid "Invalid LDAP TLS certs option: %(option). Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:99
+#, python-format
+msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:189
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%s\". Format must be "
+"<ldap_attribute>:<keystone_attribute>"
+msgstr ""
+
+#: keystone/common/ldap/core.py:195
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%(item)s\". Value "
+"\"%(attr_map)s\" must use one of %(keys)s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
+#, python-format
+msgid "Duplicate name, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
+#, python-format
+msgid "Duplicate ID, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:294
+#, python-format
+msgid "LDAP %s create"
+msgstr ""
+
+#: keystone/common/ldap/core.py:372
+#, python-format
+msgid "LDAP %s update"
+msgstr ""
+
+#: keystone/common/ldap/core.py:405
+#, python-format
+msgid "LDAP %s delete"
+msgstr ""
+
+#: keystone/common/ldap/core.py:430
+#, python-format
+msgid "LDAP init: url=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:431
+#, python-format
+msgid ""
+"LDAP init: use_tls=%(use_tls)s\n"
+"tls_cacertfile=%(tls_cacertfile)s\n"
+"tls_cacertdir=%(tls_cacertdir)s\n"
+"tls_req_cert=%(tls_req_cert)s\n"
+"tls_avail=%(tls_avail)s\n"
+msgstr ""
+
+#: keystone/common/ldap/core.py:450
+msgid "Invalid TLS / LDAPS combination"
+msgstr ""
+
+#: keystone/common/ldap/core.py:454
+#, python-format
+msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available"
+msgstr ""
+
+#: keystone/common/ldap/core.py:464
+#, python-format
+msgid "tls_cacertfile %s not found or is not a file"
+msgstr ""
+
+#: keystone/common/ldap/core.py:476
+#, python-format
+msgid "tls_cacertdir %s not found or is not a directory"
+msgstr ""
+
+#: keystone/common/ldap/core.py:483
+#, python-format
+msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:497
+#, python-format
+msgid "LDAP bind: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:508
+#, python-format
+msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:514
+#, python-format
+msgid ""
+"LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, "
+"attrs=%(attrlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:567
+msgid ""
+"LDAP Server does not support paging. Disable paging in keystone.conf to "
+"avoid this message."
+msgstr ""
+
+#: keystone/common/ldap/core.py:584
+#, python-format
+msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:590
+#, python-format
+msgid "LDAP delete: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:595
+#, python-format
+msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:146
+#, python-format
+msgid "FakeLdap initialize url=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:156
+#, python-format
+msgid "FakeLdap bind dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:163
+#, python-format
+msgid "FakeLdap bind fail: dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:170
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:175
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s does not match"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:190
+#, python-format
+msgid "FakeLdap add item: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:193
+#, python-format
+msgid "FakeLdap add item failed: dn=%s is already in store."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:207 keystone/common/ldap/fakeldap.py:221
+#, python-format
+msgid "FakeLdap delete item: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:211 keystone/common/ldap/fakeldap.py:225
+#, python-format
+msgid "FakeLdap delete item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:240
+#, python-format
+msgid "FakeLdap modify item: dn=%(dn)s attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:245
+#, python-format
+msgid "FakeLdap modify item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:262
+#, python-format
+msgid "FakeLdap modify item failed: item has no attribute \"%s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:273
+#, python-format
+msgid ""
+"FakeLdap modify item failed: item has no attribute \"%(k)s\" with value "
+"\"%(v)s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:279
+#, python-format
+msgid "FakeLdap modify item failed: unknown command %s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:281
+#, python-format
+msgid "modify_s action %s not implemented"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:300
+#, python-format
+msgid "FakeLdap search at dn=%(dn)s scope=%(scope)s query=%(query)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:306
+msgid "FakeLdap search fail: dn not found for SCOPE_BASE"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:320
+#, python-format
+msgid "Search scope %s not implemented."
+msgstr ""
+
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
+#, python-format
+msgid "Got mysql server has gone away: %s"
+msgstr ""
+
+#: keystone/common/sql/legacy.py:188
+#, python-format
+msgid "Cannot migrate EC2 credential: %s"
+msgstr ""
+
+#: keystone/common/sql/migration.py:47
+msgid "version should be an integer"
+msgstr ""
+
+#: keystone/common/sql/nova.py:65
+#, python-format
+msgid "Create tenant %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:82
+#, python-format
+msgid "Create user %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:91
+#, python-format
+msgid "Add user %(user_id)s to tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:100
+#, python-format
+msgid "Ignoring existing role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:107
+#, python-format
+msgid "Create role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:117
+#, python-format
+msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:136
+#, python-format
+msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/identity/controllers.py:952
+#, python-format
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
+msgstr ""
+
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
+msgid "User not found in group"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:189
+#, python-format
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:334
+msgid "Changing Name not supported by LDAP"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:347
+#, python-format
+msgid "User %(user_id)s is already a member of group %(group_id)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:394
+#, python-format
+msgid "Failed to understand rule %(rule)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:404
+#, python-format
+msgid "No handler for matches of kind %s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:679
+#, python-format
+msgid "Failed to understand rule %(rule)r"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
+#: keystone/policy/backends/rules.py:93
+#, python-format
+msgid "enforce %(action)s: %(credentials)s"
+msgstr ""
+
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
+msgid "Token does not belong to specified tenant."
+msgstr ""
+
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
+msgstr ""
+
+#: keystone/token/backends/memcache.py:144
+#, python-format
+msgid ""
+"Successful set of token-index-list for user-key \"%(user_key)s\", "
+"#%(count)d records"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:154
+#, python-format
+msgid ""
+"Failed to set token-index-list for user-key \"%(user_key)s\". Attempt "
+"%(cas_retry)d of %(cas_retry_max)d"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:163
+msgid "Unable to add token user list"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:172
+msgid "Unable to add token to revocation list."
+msgstr ""
+
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
diff --git a/keystone/locale/ja/LC_MESSAGES/keystone.po b/keystone/locale/ja/LC_MESSAGES/keystone.po
index 01c80b56..a8f0bb69 100644
--- a/keystone/locale/ja/LC_MESSAGES/keystone.po
+++ b/keystone/locale/ja/LC_MESSAGES/keystone.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Keystone\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2013-06-17 17:09+0000\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
"PO-Revision-Date: 2012-11-03 01:25+0000\n"
"Last-Translator: Tomoyuki KATO <tomo@dream.daynight.jp>\n"
"Language-Team: Japanese "
@@ -16,7 +16,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.6\n"
+"Generated-By: Babel 1.3\n"
#: keystone/clean.py:23
#, python-format
@@ -38,63 +38,224 @@ msgstr ""
msgid "%(property_name)s is not a %(display_expected_type)s"
msgstr ""
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
#: keystone/test.py:117
#, python-format
msgid "Failed to checkout %s"
msgstr ""
-#: keystone/auth/controllers.py:72
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr ""
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr ""
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
#, python-format
msgid "Project is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:78 keystone/auth/plugins/password.py:39
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
#, python-format
msgid "Domain is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:84 keystone/auth/plugins/password.py:45
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
#, python-format
msgid "User is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:265
+#: keystone/auth/controllers.py:262
msgid "Scoping to both domain and project is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:268
+#: keystone/auth/controllers.py:265
msgid "Scoping to both domain and trust is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:271
+#: keystone/auth/controllers.py:268
msgid "Scoping to both project and trust is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:333
-#, fuzzy, python-format
-msgid "Unable to lookup user %s"
-msgstr "ユーザーリストã«ãƒˆãƒ¼ã‚¯ãƒ³ã‚’追加ã§ãã¾ã›ã‚“。"
-
-#: keystone/auth/controllers.py:363
+#: keystone/auth/controllers.py:353
msgid "User not found"
msgstr ""
-#: keystone/auth/token_factory.py:81
-msgid "User have no access to project"
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
msgstr ""
-#: keystone/auth/token_factory.py:96
-msgid "User have no access to domain"
-msgstr ""
-
-#: keystone/auth/token_factory.py:314 keystone/token/controllers.py:121
-#, fuzzy
-msgid "Unable to sign token."
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
+#, fuzzy, python-format
+msgid "Unable to lookup user %s"
msgstr "ユーザーリストã«ãƒˆãƒ¼ã‚¯ãƒ³ã‚’追加ã§ãã¾ã›ã‚“。"
-#: keystone/auth/token_factory.py:317 keystone/token/controllers.py:124
-#, python-format
-msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
msgstr ""
#: keystone/catalog/core.py:38
@@ -121,18 +282,18 @@ msgstr ""
msgid "Unable to open template file %s"
msgstr ""
-#: keystone/common/cms.py:42
+#: keystone/common/cms.py:26
#, python-format
msgid "Verify error: %s"
msgstr ""
-#: keystone/common/cms.py:134
+#: keystone/common/cms.py:118
msgid ""
"Signing error: Unable to load certificate - ensure you've configured PKI "
"with 'keystone-manage pki_setup'"
msgstr ""
-#: keystone/common/cms.py:138
+#: keystone/common/cms.py:122
#, python-format
msgid "Signing error: %s"
msgstr ""
@@ -151,31 +312,31 @@ msgstr "無効㪠syslog ファシリティ"
msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
msgstr ""
-#: keystone/common/controller.py:26
+#: keystone/common/controller.py:25
msgid "RBAC: Invalid token"
msgstr ""
-#: keystone/common/controller.py:36 keystone/common/controller.py:57
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
msgid "RBAC: Invalid user"
msgstr ""
-#: keystone/common/controller.py:42
+#: keystone/common/controller.py:45
msgid "RBAC: Proceeding without project"
msgstr ""
-#: keystone/common/controller.py:62
+#: keystone/common/controller.py:65
msgid "RBAC: Proceeding without tenant"
msgstr ""
-#: keystone/common/controller.py:92 keystone/common/controller.py:144
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
msgid "RBAC: Bypassing authorization"
msgstr ""
-#: keystone/common/controller.py:101 keystone/common/controller.py:142
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
msgid "RBAC: Authorization granted"
msgstr ""
-#: keystone/common/controller.py:131
+#: keystone/common/controller.py:134
#, python-format
msgid "RBAC: Adding query filter params (%s)"
msgstr ""
@@ -184,33 +345,69 @@ msgstr ""
msgid "Invalid token in normalize_domain_id"
msgstr ""
-#: keystone/common/utils.py:232
+#: keystone/common/utils.py:233
msgid ""
"Error setting up the debug environment. Verify that the option --debug-"
"url has the format <host>:<port> and that a debugger processes is "
"listening on that port."
msgstr ""
-#: keystone/common/wsgi.py:162
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
#, python-format
msgid "arg_dict: %s"
msgstr ""
-#: keystone/common/wsgi.py:186
+#: keystone/common/wsgi.py:243
#, python-format
msgid "Authorization failed. %(exception)s from %(remote_addr)s"
msgstr ""
-#: keystone/common/wsgi.py:429
+#: keystone/common/wsgi.py:487
msgid "The resource could not be found."
msgstr ""
-#: keystone/common/wsgi_server.py:72
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
#, python-format
msgid "Starting %(arg0)s on %(host)s:%(port)s"
msgstr ""
-#: keystone/common/wsgi_server.py:132
+#: keystone/common/environment/eventlet_server.py:113
msgid "Server error"
msgstr ""
@@ -243,13 +440,13 @@ msgid ""
"\"%(attr_map)s\" must use one of %(keys)s."
msgstr ""
-#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:596
-#: keystone/identity/backends/kvs.py:624
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
#, python-format
msgid "Duplicate name, %s."
msgstr ""
-#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:589
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
#, python-format
msgid "Duplicate ID, %s."
msgstr ""
@@ -437,12 +634,16 @@ msgstr ""
msgid "Search scope %s not implemented."
msgstr ""
-#: keystone/common/sql/core.py:205
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
#, python-format
msgid "Got mysql server has gone away: %s"
msgstr ""
-#: keystone/common/sql/legacy.py:180
+#: keystone/common/sql/legacy.py:188
#, python-format
msgid "Cannot migrate EC2 credential: %s"
msgstr ""
@@ -451,76 +652,68 @@ msgstr ""
msgid "version should be an integer"
msgstr ""
-#: keystone/common/sql/nova.py:62
+#: keystone/common/sql/nova.py:65
#, python-format
msgid "Create tenant %s"
msgstr ""
-#: keystone/common/sql/nova.py:79
+#: keystone/common/sql/nova.py:82
#, python-format
msgid "Create user %s"
msgstr ""
-#: keystone/common/sql/nova.py:88
+#: keystone/common/sql/nova.py:91
#, python-format
msgid "Add user %(user_id)s to tenant %(tenant_id)s"
msgstr ""
-#: keystone/common/sql/nova.py:97
+#: keystone/common/sql/nova.py:100
#, python-format
msgid "Ignoring existing role %s"
msgstr ""
-#: keystone/common/sql/nova.py:104
+#: keystone/common/sql/nova.py:107
#, python-format
msgid "Create role %s"
msgstr ""
-#: keystone/common/sql/nova.py:114
+#: keystone/common/sql/nova.py:117
#, python-format
msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
msgstr ""
-#: keystone/common/sql/nova.py:133
+#: keystone/common/sql/nova.py:136
#, python-format
msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
msgstr ""
-#: keystone/identity/backends/kvs.py:250 keystone/identity/backends/kvs.py:259
-msgid "User not found in group"
-msgstr ""
-
-#: keystone/identity/backends/sql.py:425
+#: keystone/identity/controllers.py:952
#, python-format
-msgid "Cannot remove role that has not been granted, %s"
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:82
-#, python-format
-msgid "Expected dict or list: %s"
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
+msgid "User not found in group"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:681
+#: keystone/identity/backends/ldap.py:189
#, python-format
-msgid "Role %s not found"
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
msgstr ""
-#: keystone/identity/backends/ldap/core.py:898
+#: keystone/identity/backends/ldap.py:334
msgid "Changing Name not supported by LDAP"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:911
+#: keystone/identity/backends/ldap.py:347
#, python-format
msgid "User %(user_id)s is already a member of group %(group_id)s"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:954
-#, python-format
-msgid ""
-"Group member '%(user_dn)s' not found in '%(group_dn)s'. The user should "
-"be removed from the group. The user will be ignored."
-msgstr ""
-
#: keystone/openstack/common/policy.py:394
#, python-format
msgid "Failed to understand rule %(rule)s"
@@ -536,21 +729,56 @@ msgstr ""
msgid "Failed to understand rule %(rule)r"
msgstr ""
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
#: keystone/policy/backends/rules.py:93
#, python-format
msgid "enforce %(action)s: %(credentials)s"
msgstr ""
-#: keystone/token/controllers.py:465 keystone/token/controllers.py:468
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
msgid "Token does not belong to specified tenant."
msgstr ""
-#: keystone/token/controllers.py:475
-msgid "Non-default domain is not supported"
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
msgstr ""
-#: keystone/token/controllers.py:483
-msgid "Domain scoped token is not supported"
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
msgstr ""
#: keystone/token/backends/memcache.py:144
@@ -575,3 +803,55 @@ msgstr ""
msgid "Unable to add token to revocation list."
msgstr "失効リストã«ãƒˆãƒ¼ã‚¯ãƒ³ã‚’追加ã§ãã¾ã›ã‚“。"
+#: keystone/token/providers/pki.py:43
+#, fuzzy
+msgid "Unable to sign token."
+msgstr "ユーザーリストã«ãƒˆãƒ¼ã‚¯ãƒ³ã‚’追加ã§ãã¾ã›ã‚“。"
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
+#~ msgid "User have no access to project"
+#~ msgstr ""
+
+#~ msgid "User have no access to domain"
+#~ msgstr ""
+
+#~ msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+#~ msgstr ""
+
diff --git a/keystone/locale/ka_GE/LC_MESSAGES/keystone.po b/keystone/locale/ka_GE/LC_MESSAGES/keystone.po
index 283cee63..8d998614 100644
--- a/keystone/locale/ka_GE/LC_MESSAGES/keystone.po
+++ b/keystone/locale/ka_GE/LC_MESSAGES/keystone.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Keystone\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2013-06-17 17:09+0000\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
"PO-Revision-Date: 2013-05-17 16:06+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
"Language-Team: ka_GE <LL@li.org>\n"
@@ -16,7 +16,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.6\n"
+"Generated-By: Babel 1.3\n"
#: keystone/clean.py:23
#, python-format
@@ -38,62 +38,224 @@ msgstr ""
msgid "%(property_name)s is not a %(display_expected_type)s"
msgstr ""
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
#: keystone/test.py:117
#, python-format
msgid "Failed to checkout %s"
msgstr ""
-#: keystone/auth/controllers.py:72
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr ""
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr "რáƒáƒšáƒ˜ %s ვერ მáƒáƒ˜áƒ«áƒ”ბნáƒ"
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
#, python-format
msgid "Project is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:78 keystone/auth/plugins/password.py:39
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
#, python-format
msgid "Domain is disabled: %s"
msgstr "დáƒáƒ›áƒ”ნი გáƒáƒ—იშულიáƒ: %s"
-#: keystone/auth/controllers.py:84 keystone/auth/plugins/password.py:45
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
#, python-format
msgid "User is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:265
+#: keystone/auth/controllers.py:262
msgid "Scoping to both domain and project is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:268
+#: keystone/auth/controllers.py:265
msgid "Scoping to both domain and trust is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:271
+#: keystone/auth/controllers.py:268
msgid "Scoping to both project and trust is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:333
-#, python-format
-msgid "Unable to lookup user %s"
-msgstr ""
-
-#: keystone/auth/controllers.py:363
+#: keystone/auth/controllers.py:353
msgid "User not found"
msgstr "მáƒáƒ›áƒ®áƒ›áƒáƒ áƒ”ბელი ვერ მáƒáƒ˜áƒ«áƒ”ბნáƒ"
-#: keystone/auth/token_factory.py:81
-msgid "User have no access to project"
-msgstr "მáƒáƒ›áƒ®áƒ›áƒáƒ áƒ”ბელს áƒáƒ  áƒáƒ¥áƒ•áƒ¡ წვდáƒáƒ›áƒ პრáƒáƒ”ქტზე"
-
-#: keystone/auth/token_factory.py:96
-msgid "User have no access to domain"
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
msgstr ""
-#: keystone/auth/token_factory.py:314 keystone/token/controllers.py:121
-msgid "Unable to sign token."
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
+#, python-format
+msgid "Unable to lookup user %s"
msgstr ""
-#: keystone/auth/token_factory.py:317 keystone/token/controllers.py:124
-#, python-format
-msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
msgstr ""
#: keystone/catalog/core.py:38
@@ -120,18 +282,18 @@ msgstr ""
msgid "Unable to open template file %s"
msgstr ""
-#: keystone/common/cms.py:42
+#: keystone/common/cms.py:26
#, python-format
msgid "Verify error: %s"
msgstr ""
-#: keystone/common/cms.py:134
+#: keystone/common/cms.py:118
msgid ""
"Signing error: Unable to load certificate - ensure you've configured PKI "
"with 'keystone-manage pki_setup'"
msgstr ""
-#: keystone/common/cms.py:138
+#: keystone/common/cms.py:122
#, python-format
msgid "Signing error: %s"
msgstr ""
@@ -150,31 +312,31 @@ msgstr ""
msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
msgstr ""
-#: keystone/common/controller.py:26
+#: keystone/common/controller.py:25
msgid "RBAC: Invalid token"
msgstr ""
-#: keystone/common/controller.py:36 keystone/common/controller.py:57
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
msgid "RBAC: Invalid user"
msgstr ""
-#: keystone/common/controller.py:42
+#: keystone/common/controller.py:45
msgid "RBAC: Proceeding without project"
msgstr ""
-#: keystone/common/controller.py:62
+#: keystone/common/controller.py:65
msgid "RBAC: Proceeding without tenant"
msgstr ""
-#: keystone/common/controller.py:92 keystone/common/controller.py:144
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
msgid "RBAC: Bypassing authorization"
msgstr ""
-#: keystone/common/controller.py:101 keystone/common/controller.py:142
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
msgid "RBAC: Authorization granted"
msgstr ""
-#: keystone/common/controller.py:131
+#: keystone/common/controller.py:134
#, python-format
msgid "RBAC: Adding query filter params (%s)"
msgstr ""
@@ -183,33 +345,69 @@ msgstr ""
msgid "Invalid token in normalize_domain_id"
msgstr ""
-#: keystone/common/utils.py:232
+#: keystone/common/utils.py:233
msgid ""
"Error setting up the debug environment. Verify that the option --debug-"
"url has the format <host>:<port> and that a debugger processes is "
"listening on that port."
msgstr ""
-#: keystone/common/wsgi.py:162
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
#, python-format
msgid "arg_dict: %s"
msgstr ""
-#: keystone/common/wsgi.py:186
+#: keystone/common/wsgi.py:243
#, python-format
msgid "Authorization failed. %(exception)s from %(remote_addr)s"
msgstr ""
-#: keystone/common/wsgi.py:429
+#: keystone/common/wsgi.py:487
msgid "The resource could not be found."
msgstr ""
-#: keystone/common/wsgi_server.py:72
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
#, python-format
msgid "Starting %(arg0)s on %(host)s:%(port)s"
msgstr ""
-#: keystone/common/wsgi_server.py:132
+#: keystone/common/environment/eventlet_server.py:113
msgid "Server error"
msgstr ""
@@ -242,13 +440,13 @@ msgid ""
"\"%(attr_map)s\" must use one of %(keys)s."
msgstr ""
-#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:596
-#: keystone/identity/backends/kvs.py:624
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
#, python-format
msgid "Duplicate name, %s."
msgstr ""
-#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:589
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
#, python-format
msgid "Duplicate ID, %s."
msgstr ""
@@ -436,12 +634,16 @@ msgstr ""
msgid "Search scope %s not implemented."
msgstr ""
-#: keystone/common/sql/core.py:205
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
#, python-format
msgid "Got mysql server has gone away: %s"
msgstr ""
-#: keystone/common/sql/legacy.py:180
+#: keystone/common/sql/legacy.py:188
#, python-format
msgid "Cannot migrate EC2 credential: %s"
msgstr ""
@@ -450,76 +652,68 @@ msgstr ""
msgid "version should be an integer"
msgstr ""
-#: keystone/common/sql/nova.py:62
+#: keystone/common/sql/nova.py:65
#, python-format
msgid "Create tenant %s"
msgstr ""
-#: keystone/common/sql/nova.py:79
+#: keystone/common/sql/nova.py:82
#, python-format
msgid "Create user %s"
msgstr "მáƒáƒ›áƒ®áƒ›áƒáƒ áƒ”ბლის შექმნრ%s"
-#: keystone/common/sql/nova.py:88
+#: keystone/common/sql/nova.py:91
#, python-format
msgid "Add user %(user_id)s to tenant %(tenant_id)s"
msgstr ""
-#: keystone/common/sql/nova.py:97
+#: keystone/common/sql/nova.py:100
#, python-format
msgid "Ignoring existing role %s"
msgstr ""
-#: keystone/common/sql/nova.py:104
+#: keystone/common/sql/nova.py:107
#, python-format
msgid "Create role %s"
msgstr ""
-#: keystone/common/sql/nova.py:114
+#: keystone/common/sql/nova.py:117
#, python-format
msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
msgstr ""
-#: keystone/common/sql/nova.py:133
+#: keystone/common/sql/nova.py:136
#, python-format
msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
msgstr ""
-#: keystone/identity/backends/kvs.py:250 keystone/identity/backends/kvs.py:259
-msgid "User not found in group"
-msgstr ""
-
-#: keystone/identity/backends/sql.py:425
+#: keystone/identity/controllers.py:952
#, python-format
-msgid "Cannot remove role that has not been granted, %s"
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:82
-#, python-format
-msgid "Expected dict or list: %s"
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
+msgid "User not found in group"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:681
+#: keystone/identity/backends/ldap.py:189
#, python-format
-msgid "Role %s not found"
-msgstr "რáƒáƒšáƒ˜ %s ვერ მáƒáƒ˜áƒ«áƒ”ბნáƒ"
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
+msgstr ""
-#: keystone/identity/backends/ldap/core.py:898
+#: keystone/identity/backends/ldap.py:334
msgid "Changing Name not supported by LDAP"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:911
+#: keystone/identity/backends/ldap.py:347
#, python-format
msgid "User %(user_id)s is already a member of group %(group_id)s"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:954
-#, python-format
-msgid ""
-"Group member '%(user_dn)s' not found in '%(group_dn)s'. The user should "
-"be removed from the group. The user will be ignored."
-msgstr ""
-
#: keystone/openstack/common/policy.py:394
#, python-format
msgid "Failed to understand rule %(rule)s"
@@ -535,21 +729,56 @@ msgstr ""
msgid "Failed to understand rule %(rule)r"
msgstr ""
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
#: keystone/policy/backends/rules.py:93
#, python-format
msgid "enforce %(action)s: %(credentials)s"
msgstr ""
-#: keystone/token/controllers.py:465 keystone/token/controllers.py:468
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
msgid "Token does not belong to specified tenant."
msgstr ""
-#: keystone/token/controllers.py:475
-msgid "Non-default domain is not supported"
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
msgstr ""
-#: keystone/token/controllers.py:483
-msgid "Domain scoped token is not supported"
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
msgstr ""
#: keystone/token/backends/memcache.py:144
@@ -574,3 +803,54 @@ msgstr ""
msgid "Unable to add token to revocation list."
msgstr ""
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
+#~ msgid "User have no access to project"
+#~ msgstr "მáƒáƒ›áƒ®áƒ›áƒáƒ áƒ”ბელს áƒáƒ  áƒáƒ¥áƒ•áƒ¡ წვდáƒáƒ›áƒ პრáƒáƒ”ქტზე"
+
+#~ msgid "User have no access to domain"
+#~ msgstr ""
+
+#~ msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+#~ msgstr ""
+
diff --git a/keystone/locale/keystone.pot b/keystone/locale/keystone.pot
index 663e2f7f..718b35c8 100644
--- a/keystone/locale/keystone.pot
+++ b/keystone/locale/keystone.pot
@@ -7,16 +7,16 @@
msgid ""
msgstr ""
"Project-Id-Version: keystone "
-"jenkins.keystone.propose.translation.update.234\n"
+"jenkins.keystone.propose.translation.update.280\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
-"POT-Creation-Date: 2013-06-17 17:09+0000\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.6\n"
+"Generated-By: Babel 1.3\n"
#: keystone/clean.py:23
#, python-format
@@ -38,62 +38,224 @@ msgstr ""
msgid "%(property_name)s is not a %(display_expected_type)s"
msgstr ""
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
#: keystone/test.py:117
#, python-format
msgid "Failed to checkout %s"
msgstr ""
-#: keystone/auth/controllers.py:72
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr ""
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr ""
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
#, python-format
msgid "Project is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:78 keystone/auth/plugins/password.py:39
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
#, python-format
msgid "Domain is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:84 keystone/auth/plugins/password.py:45
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
#, python-format
msgid "User is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:265
+#: keystone/auth/controllers.py:262
msgid "Scoping to both domain and project is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:268
+#: keystone/auth/controllers.py:265
msgid "Scoping to both domain and trust is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:271
+#: keystone/auth/controllers.py:268
msgid "Scoping to both project and trust is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:333
-#, python-format
-msgid "Unable to lookup user %s"
-msgstr ""
-
-#: keystone/auth/controllers.py:363
+#: keystone/auth/controllers.py:353
msgid "User not found"
msgstr ""
-#: keystone/auth/token_factory.py:81
-msgid "User have no access to project"
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
msgstr ""
-#: keystone/auth/token_factory.py:96
-msgid "User have no access to domain"
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
+#, python-format
+msgid "Unable to lookup user %s"
msgstr ""
-#: keystone/auth/token_factory.py:314 keystone/token/controllers.py:121
-msgid "Unable to sign token."
-msgstr ""
-
-#: keystone/auth/token_factory.py:317 keystone/token/controllers.py:124
-#, python-format
-msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
msgstr ""
#: keystone/catalog/core.py:38
@@ -120,18 +282,18 @@ msgstr ""
msgid "Unable to open template file %s"
msgstr ""
-#: keystone/common/cms.py:42
+#: keystone/common/cms.py:26
#, python-format
msgid "Verify error: %s"
msgstr ""
-#: keystone/common/cms.py:134
+#: keystone/common/cms.py:118
msgid ""
"Signing error: Unable to load certificate - ensure you've configured PKI "
"with 'keystone-manage pki_setup'"
msgstr ""
-#: keystone/common/cms.py:138
+#: keystone/common/cms.py:122
#, python-format
msgid "Signing error: %s"
msgstr ""
@@ -150,31 +312,31 @@ msgstr ""
msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
msgstr ""
-#: keystone/common/controller.py:26
+#: keystone/common/controller.py:25
msgid "RBAC: Invalid token"
msgstr ""
-#: keystone/common/controller.py:36 keystone/common/controller.py:57
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
msgid "RBAC: Invalid user"
msgstr ""
-#: keystone/common/controller.py:42
+#: keystone/common/controller.py:45
msgid "RBAC: Proceeding without project"
msgstr ""
-#: keystone/common/controller.py:62
+#: keystone/common/controller.py:65
msgid "RBAC: Proceeding without tenant"
msgstr ""
-#: keystone/common/controller.py:92 keystone/common/controller.py:144
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
msgid "RBAC: Bypassing authorization"
msgstr ""
-#: keystone/common/controller.py:101 keystone/common/controller.py:142
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
msgid "RBAC: Authorization granted"
msgstr ""
-#: keystone/common/controller.py:131
+#: keystone/common/controller.py:134
#, python-format
msgid "RBAC: Adding query filter params (%s)"
msgstr ""
@@ -183,33 +345,69 @@ msgstr ""
msgid "Invalid token in normalize_domain_id"
msgstr ""
-#: keystone/common/utils.py:232
+#: keystone/common/utils.py:233
msgid ""
"Error setting up the debug environment. Verify that the option --debug-"
"url has the format <host>:<port> and that a debugger processes is "
"listening on that port."
msgstr ""
-#: keystone/common/wsgi.py:162
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
#, python-format
msgid "arg_dict: %s"
msgstr ""
-#: keystone/common/wsgi.py:186
+#: keystone/common/wsgi.py:243
#, python-format
msgid "Authorization failed. %(exception)s from %(remote_addr)s"
msgstr ""
-#: keystone/common/wsgi.py:429
+#: keystone/common/wsgi.py:487
msgid "The resource could not be found."
msgstr ""
-#: keystone/common/wsgi_server.py:72
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
#, python-format
msgid "Starting %(arg0)s on %(host)s:%(port)s"
msgstr ""
-#: keystone/common/wsgi_server.py:132
+#: keystone/common/environment/eventlet_server.py:113
msgid "Server error"
msgstr ""
@@ -242,13 +440,13 @@ msgid ""
"\"%(attr_map)s\" must use one of %(keys)s."
msgstr ""
-#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:596
-#: keystone/identity/backends/kvs.py:624
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
#, python-format
msgid "Duplicate name, %s."
msgstr ""
-#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:589
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
#, python-format
msgid "Duplicate ID, %s."
msgstr ""
@@ -436,12 +634,16 @@ msgstr ""
msgid "Search scope %s not implemented."
msgstr ""
-#: keystone/common/sql/core.py:205
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
#, python-format
msgid "Got mysql server has gone away: %s"
msgstr ""
-#: keystone/common/sql/legacy.py:180
+#: keystone/common/sql/legacy.py:188
#, python-format
msgid "Cannot migrate EC2 credential: %s"
msgstr ""
@@ -450,76 +652,68 @@ msgstr ""
msgid "version should be an integer"
msgstr ""
-#: keystone/common/sql/nova.py:62
+#: keystone/common/sql/nova.py:65
#, python-format
msgid "Create tenant %s"
msgstr ""
-#: keystone/common/sql/nova.py:79
+#: keystone/common/sql/nova.py:82
#, python-format
msgid "Create user %s"
msgstr ""
-#: keystone/common/sql/nova.py:88
+#: keystone/common/sql/nova.py:91
#, python-format
msgid "Add user %(user_id)s to tenant %(tenant_id)s"
msgstr ""
-#: keystone/common/sql/nova.py:97
+#: keystone/common/sql/nova.py:100
#, python-format
msgid "Ignoring existing role %s"
msgstr ""
-#: keystone/common/sql/nova.py:104
+#: keystone/common/sql/nova.py:107
#, python-format
msgid "Create role %s"
msgstr ""
-#: keystone/common/sql/nova.py:114
+#: keystone/common/sql/nova.py:117
#, python-format
msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
msgstr ""
-#: keystone/common/sql/nova.py:133
+#: keystone/common/sql/nova.py:136
#, python-format
msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
msgstr ""
-#: keystone/identity/backends/kvs.py:250 keystone/identity/backends/kvs.py:259
-msgid "User not found in group"
-msgstr ""
-
-#: keystone/identity/backends/sql.py:425
+#: keystone/identity/controllers.py:952
#, python-format
-msgid "Cannot remove role that has not been granted, %s"
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:82
-#, python-format
-msgid "Expected dict or list: %s"
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
+msgid "User not found in group"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:681
+#: keystone/identity/backends/ldap.py:189
#, python-format
-msgid "Role %s not found"
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
msgstr ""
-#: keystone/identity/backends/ldap/core.py:898
+#: keystone/identity/backends/ldap.py:334
msgid "Changing Name not supported by LDAP"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:911
+#: keystone/identity/backends/ldap.py:347
#, python-format
msgid "User %(user_id)s is already a member of group %(group_id)s"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:954
-#, python-format
-msgid ""
-"Group member '%(user_dn)s' not found in '%(group_dn)s'. The user should "
-"be removed from the group. The user will be ignored."
-msgstr ""
-
#: keystone/openstack/common/policy.py:394
#, python-format
msgid "Failed to understand rule %(rule)s"
@@ -535,21 +729,56 @@ msgstr ""
msgid "Failed to understand rule %(rule)r"
msgstr ""
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
#: keystone/policy/backends/rules.py:93
#, python-format
msgid "enforce %(action)s: %(credentials)s"
msgstr ""
-#: keystone/token/controllers.py:465 keystone/token/controllers.py:468
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
msgid "Token does not belong to specified tenant."
msgstr ""
-#: keystone/token/controllers.py:475
-msgid "Non-default domain is not supported"
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
msgstr ""
-#: keystone/token/controllers.py:483
-msgid "Domain scoped token is not supported"
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
msgstr ""
#: keystone/token/backends/memcache.py:144
@@ -574,3 +803,45 @@ msgstr ""
msgid "Unable to add token to revocation list."
msgstr ""
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
diff --git a/keystone/locale/ko/LC_MESSAGES/keystone.po b/keystone/locale/ko/LC_MESSAGES/keystone.po
new file mode 100644
index 00000000..cb047f5f
--- /dev/null
+++ b/keystone/locale/ko/LC_MESSAGES/keystone.po
@@ -0,0 +1,847 @@
+# Korean translations for keystone.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the keystone project.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: Keystone\n"
+"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
+"PO-Revision-Date: 2013-07-29 22:01+0000\n"
+"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
+"Language-Team: Korean "
+"(http://www.transifex.com/projects/p/openstack/language/ko/)\n"
+"Plural-Forms: nplurals=1; plural=0\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: keystone/clean.py:23
+#, python-format
+msgid "%s cannot be empty."
+msgstr ""
+
+#: keystone/clean.py:25
+#, python-format
+msgid "%(property_name)s cannot be less than %(min_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:29
+#, python-format
+msgid "%(property_name)s should not be greater than %(max_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:36
+#, python-format
+msgid "%(property_name)s is not a %(display_expected_type)s"
+msgstr ""
+
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
+#: keystone/test.py:117
+#, python-format
+msgid "Failed to checkout %s"
+msgstr ""
+
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr ""
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr ""
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
+#, python-format
+msgid "Project is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
+#, python-format
+msgid "Domain is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
+#, python-format
+msgid "User is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:262
+msgid "Scoping to both domain and project is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:265
+msgid "Scoping to both domain and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:268
+msgid "Scoping to both project and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:353
+msgid "User not found"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
+#, python-format
+msgid "Unable to lookup user %s"
+msgstr ""
+
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
+msgstr ""
+
+#: keystone/catalog/core.py:38
+#, python-format
+msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s"
+msgstr ""
+
+#: keystone/catalog/core.py:43
+#, python-format
+msgid ""
+"Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing "
+"brackets ?)"
+msgstr ""
+
+#: keystone/catalog/core.py:49
+#, python-format
+msgid ""
+"Malformed endpoint %s - incomplete format (are you "
+"missing a type notifier ?)"
+msgstr ""
+
+#: keystone/catalog/backends/templated.py:109
+#, python-format
+msgid "Unable to open template file %s"
+msgstr ""
+
+#: keystone/common/cms.py:26
+#, python-format
+msgid "Verify error: %s"
+msgstr ""
+
+#: keystone/common/cms.py:118
+msgid ""
+"Signing error: Unable to load certificate - ensure you've configured PKI "
+"with 'keystone-manage pki_setup'"
+msgstr ""
+
+#: keystone/common/cms.py:122
+#, python-format
+msgid "Signing error: %s"
+msgstr ""
+
+#: keystone/common/config.py:89
+#, python-format
+msgid "Unable to locate specified logging config file: %s"
+msgstr ""
+
+#: keystone/common/config.py:107
+msgid "Invalid syslog facility"
+msgstr ""
+
+#: keystone/common/controller.py:18
+#, python-format
+msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
+msgstr ""
+
+#: keystone/common/controller.py:25
+msgid "RBAC: Invalid token"
+msgstr ""
+
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
+msgid "RBAC: Invalid user"
+msgstr ""
+
+#: keystone/common/controller.py:45
+msgid "RBAC: Proceeding without project"
+msgstr ""
+
+#: keystone/common/controller.py:65
+msgid "RBAC: Proceeding without tenant"
+msgstr ""
+
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
+msgid "RBAC: Bypassing authorization"
+msgstr ""
+
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
+msgid "RBAC: Authorization granted"
+msgstr ""
+
+#: keystone/common/controller.py:134
+#, python-format
+msgid "RBAC: Adding query filter params (%s)"
+msgstr ""
+
+#: keystone/common/controller.py:322
+msgid "Invalid token in normalize_domain_id"
+msgstr ""
+
+#: keystone/common/utils.py:233
+msgid ""
+"Error setting up the debug environment. Verify that the option --debug-"
+"url has the format <host>:<port> and that a debugger processes is "
+"listening on that port."
+msgstr ""
+
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
+#, python-format
+msgid "arg_dict: %s"
+msgstr ""
+
+#: keystone/common/wsgi.py:243
+#, python-format
+msgid "Authorization failed. %(exception)s from %(remote_addr)s"
+msgstr ""
+
+#: keystone/common/wsgi.py:487
+msgid "The resource could not be found."
+msgstr ""
+
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
+#, python-format
+msgid "Starting %(arg0)s on %(host)s:%(port)s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:113
+msgid "Server error"
+msgstr ""
+
+#: keystone/common/ldap/core.py:79
+#, python-format
+msgid "Invalid LDAP deref option: %s. Choose one of: "
+msgstr ""
+
+#: keystone/common/ldap/core.py:87
+#, python-format
+msgid "Invalid LDAP TLS certs option: %(option). Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:99
+#, python-format
+msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:189
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%s\". Format must be "
+"<ldap_attribute>:<keystone_attribute>"
+msgstr ""
+
+#: keystone/common/ldap/core.py:195
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%(item)s\". Value "
+"\"%(attr_map)s\" must use one of %(keys)s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
+#, python-format
+msgid "Duplicate name, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
+#, python-format
+msgid "Duplicate ID, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:294
+#, python-format
+msgid "LDAP %s create"
+msgstr ""
+
+#: keystone/common/ldap/core.py:372
+#, python-format
+msgid "LDAP %s update"
+msgstr ""
+
+#: keystone/common/ldap/core.py:405
+#, python-format
+msgid "LDAP %s delete"
+msgstr ""
+
+#: keystone/common/ldap/core.py:430
+#, python-format
+msgid "LDAP init: url=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:431
+#, python-format
+msgid ""
+"LDAP init: use_tls=%(use_tls)s\n"
+"tls_cacertfile=%(tls_cacertfile)s\n"
+"tls_cacertdir=%(tls_cacertdir)s\n"
+"tls_req_cert=%(tls_req_cert)s\n"
+"tls_avail=%(tls_avail)s\n"
+msgstr ""
+
+#: keystone/common/ldap/core.py:450
+msgid "Invalid TLS / LDAPS combination"
+msgstr ""
+
+#: keystone/common/ldap/core.py:454
+#, python-format
+msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available"
+msgstr ""
+
+#: keystone/common/ldap/core.py:464
+#, python-format
+msgid "tls_cacertfile %s not found or is not a file"
+msgstr ""
+
+#: keystone/common/ldap/core.py:476
+#, python-format
+msgid "tls_cacertdir %s not found or is not a directory"
+msgstr ""
+
+#: keystone/common/ldap/core.py:483
+#, python-format
+msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:497
+#, python-format
+msgid "LDAP bind: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:508
+#, python-format
+msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:514
+#, python-format
+msgid ""
+"LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, "
+"attrs=%(attrlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:567
+msgid ""
+"LDAP Server does not support paging. Disable paging in keystone.conf to "
+"avoid this message."
+msgstr ""
+
+#: keystone/common/ldap/core.py:584
+#, python-format
+msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:590
+#, python-format
+msgid "LDAP delete: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:595
+#, python-format
+msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:146
+#, python-format
+msgid "FakeLdap initialize url=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:156
+#, python-format
+msgid "FakeLdap bind dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:163
+#, python-format
+msgid "FakeLdap bind fail: dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:170
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:175
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s does not match"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:190
+#, python-format
+msgid "FakeLdap add item: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:193
+#, python-format
+msgid "FakeLdap add item failed: dn=%s is already in store."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:207 keystone/common/ldap/fakeldap.py:221
+#, python-format
+msgid "FakeLdap delete item: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:211 keystone/common/ldap/fakeldap.py:225
+#, python-format
+msgid "FakeLdap delete item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:240
+#, python-format
+msgid "FakeLdap modify item: dn=%(dn)s attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:245
+#, python-format
+msgid "FakeLdap modify item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:262
+#, python-format
+msgid "FakeLdap modify item failed: item has no attribute \"%s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:273
+#, python-format
+msgid ""
+"FakeLdap modify item failed: item has no attribute \"%(k)s\" with value "
+"\"%(v)s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:279
+#, python-format
+msgid "FakeLdap modify item failed: unknown command %s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:281
+#, python-format
+msgid "modify_s action %s not implemented"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:300
+#, python-format
+msgid "FakeLdap search at dn=%(dn)s scope=%(scope)s query=%(query)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:306
+msgid "FakeLdap search fail: dn not found for SCOPE_BASE"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:320
+#, python-format
+msgid "Search scope %s not implemented."
+msgstr ""
+
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
+#, python-format
+msgid "Got mysql server has gone away: %s"
+msgstr ""
+
+#: keystone/common/sql/legacy.py:188
+#, python-format
+msgid "Cannot migrate EC2 credential: %s"
+msgstr ""
+
+#: keystone/common/sql/migration.py:47
+msgid "version should be an integer"
+msgstr ""
+
+#: keystone/common/sql/nova.py:65
+#, python-format
+msgid "Create tenant %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:82
+#, python-format
+msgid "Create user %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:91
+#, python-format
+msgid "Add user %(user_id)s to tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:100
+#, python-format
+msgid "Ignoring existing role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:107
+#, python-format
+msgid "Create role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:117
+#, python-format
+msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:136
+#, python-format
+msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/identity/controllers.py:952
+#, python-format
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
+msgstr ""
+
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
+msgid "User not found in group"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:189
+#, python-format
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:334
+msgid "Changing Name not supported by LDAP"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:347
+#, python-format
+msgid "User %(user_id)s is already a member of group %(group_id)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:394
+#, python-format
+msgid "Failed to understand rule %(rule)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:404
+#, python-format
+msgid "No handler for matches of kind %s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:679
+#, python-format
+msgid "Failed to understand rule %(rule)r"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
+#: keystone/policy/backends/rules.py:93
+#, python-format
+msgid "enforce %(action)s: %(credentials)s"
+msgstr ""
+
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
+msgid "Token does not belong to specified tenant."
+msgstr ""
+
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
+msgstr ""
+
+#: keystone/token/backends/memcache.py:144
+#, python-format
+msgid ""
+"Successful set of token-index-list for user-key \"%(user_key)s\", "
+"#%(count)d records"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:154
+#, python-format
+msgid ""
+"Failed to set token-index-list for user-key \"%(user_key)s\". Attempt "
+"%(cas_retry)d of %(cas_retry_max)d"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:163
+msgid "Unable to add token user list"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:172
+msgid "Unable to add token to revocation list."
+msgstr ""
+
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
diff --git a/keystone/locale/ko_KR/LC_MESSAGES/keystone.po b/keystone/locale/ko_KR/LC_MESSAGES/keystone.po
index d80557dd..733aef75 100644
--- a/keystone/locale/ko_KR/LC_MESSAGES/keystone.po
+++ b/keystone/locale/ko_KR/LC_MESSAGES/keystone.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Keystone\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2013-06-17 17:09+0000\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
"PO-Revision-Date: 2013-03-21 18:34+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
"Language-Team: ko_KR <LL@li.org>\n"
@@ -16,7 +16,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.6\n"
+"Generated-By: Babel 1.3\n"
#: keystone/clean.py:23
#, python-format
@@ -38,62 +38,224 @@ msgstr ""
msgid "%(property_name)s is not a %(display_expected_type)s"
msgstr ""
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
#: keystone/test.py:117
#, python-format
msgid "Failed to checkout %s"
msgstr ""
-#: keystone/auth/controllers.py:72
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr ""
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr ""
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
#, python-format
msgid "Project is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:78 keystone/auth/plugins/password.py:39
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
#, python-format
msgid "Domain is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:84 keystone/auth/plugins/password.py:45
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
#, python-format
msgid "User is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:265
+#: keystone/auth/controllers.py:262
msgid "Scoping to both domain and project is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:268
+#: keystone/auth/controllers.py:265
msgid "Scoping to both domain and trust is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:271
+#: keystone/auth/controllers.py:268
msgid "Scoping to both project and trust is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:333
-#, python-format
-msgid "Unable to lookup user %s"
-msgstr ""
-
-#: keystone/auth/controllers.py:363
+#: keystone/auth/controllers.py:353
msgid "User not found"
msgstr ""
-#: keystone/auth/token_factory.py:81
-msgid "User have no access to project"
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
msgstr ""
-#: keystone/auth/token_factory.py:96
-msgid "User have no access to domain"
-msgstr ""
-
-#: keystone/auth/token_factory.py:314 keystone/token/controllers.py:121
-msgid "Unable to sign token."
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
+#, python-format
+msgid "Unable to lookup user %s"
msgstr ""
-#: keystone/auth/token_factory.py:317 keystone/token/controllers.py:124
-#, python-format
-msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
msgstr ""
#: keystone/catalog/core.py:38
@@ -120,18 +282,18 @@ msgstr ""
msgid "Unable to open template file %s"
msgstr ""
-#: keystone/common/cms.py:42
+#: keystone/common/cms.py:26
#, python-format
msgid "Verify error: %s"
msgstr ""
-#: keystone/common/cms.py:134
+#: keystone/common/cms.py:118
msgid ""
"Signing error: Unable to load certificate - ensure you've configured PKI "
"with 'keystone-manage pki_setup'"
msgstr ""
-#: keystone/common/cms.py:138
+#: keystone/common/cms.py:122
#, python-format
msgid "Signing error: %s"
msgstr ""
@@ -150,31 +312,31 @@ msgstr ""
msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
msgstr ""
-#: keystone/common/controller.py:26
+#: keystone/common/controller.py:25
msgid "RBAC: Invalid token"
msgstr ""
-#: keystone/common/controller.py:36 keystone/common/controller.py:57
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
msgid "RBAC: Invalid user"
msgstr ""
-#: keystone/common/controller.py:42
+#: keystone/common/controller.py:45
msgid "RBAC: Proceeding without project"
msgstr ""
-#: keystone/common/controller.py:62
+#: keystone/common/controller.py:65
msgid "RBAC: Proceeding without tenant"
msgstr ""
-#: keystone/common/controller.py:92 keystone/common/controller.py:144
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
msgid "RBAC: Bypassing authorization"
msgstr ""
-#: keystone/common/controller.py:101 keystone/common/controller.py:142
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
msgid "RBAC: Authorization granted"
msgstr ""
-#: keystone/common/controller.py:131
+#: keystone/common/controller.py:134
#, python-format
msgid "RBAC: Adding query filter params (%s)"
msgstr ""
@@ -183,33 +345,69 @@ msgstr ""
msgid "Invalid token in normalize_domain_id"
msgstr ""
-#: keystone/common/utils.py:232
+#: keystone/common/utils.py:233
msgid ""
"Error setting up the debug environment. Verify that the option --debug-"
"url has the format <host>:<port> and that a debugger processes is "
"listening on that port."
msgstr ""
-#: keystone/common/wsgi.py:162
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
#, python-format
msgid "arg_dict: %s"
msgstr ""
-#: keystone/common/wsgi.py:186
+#: keystone/common/wsgi.py:243
#, python-format
msgid "Authorization failed. %(exception)s from %(remote_addr)s"
msgstr ""
-#: keystone/common/wsgi.py:429
+#: keystone/common/wsgi.py:487
msgid "The resource could not be found."
msgstr ""
-#: keystone/common/wsgi_server.py:72
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
#, python-format
msgid "Starting %(arg0)s on %(host)s:%(port)s"
msgstr ""
-#: keystone/common/wsgi_server.py:132
+#: keystone/common/environment/eventlet_server.py:113
msgid "Server error"
msgstr ""
@@ -242,13 +440,13 @@ msgid ""
"\"%(attr_map)s\" must use one of %(keys)s."
msgstr ""
-#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:596
-#: keystone/identity/backends/kvs.py:624
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
#, python-format
msgid "Duplicate name, %s."
msgstr ""
-#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:589
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
#, python-format
msgid "Duplicate ID, %s."
msgstr ""
@@ -436,12 +634,16 @@ msgstr ""
msgid "Search scope %s not implemented."
msgstr ""
-#: keystone/common/sql/core.py:205
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
#, python-format
msgid "Got mysql server has gone away: %s"
msgstr ""
-#: keystone/common/sql/legacy.py:180
+#: keystone/common/sql/legacy.py:188
#, python-format
msgid "Cannot migrate EC2 credential: %s"
msgstr ""
@@ -450,76 +652,68 @@ msgstr ""
msgid "version should be an integer"
msgstr ""
-#: keystone/common/sql/nova.py:62
+#: keystone/common/sql/nova.py:65
#, python-format
msgid "Create tenant %s"
msgstr ""
-#: keystone/common/sql/nova.py:79
+#: keystone/common/sql/nova.py:82
#, python-format
msgid "Create user %s"
msgstr ""
-#: keystone/common/sql/nova.py:88
+#: keystone/common/sql/nova.py:91
#, python-format
msgid "Add user %(user_id)s to tenant %(tenant_id)s"
msgstr ""
-#: keystone/common/sql/nova.py:97
+#: keystone/common/sql/nova.py:100
#, python-format
msgid "Ignoring existing role %s"
msgstr ""
-#: keystone/common/sql/nova.py:104
+#: keystone/common/sql/nova.py:107
#, python-format
msgid "Create role %s"
msgstr "Role %s ìƒì„±"
-#: keystone/common/sql/nova.py:114
+#: keystone/common/sql/nova.py:117
#, python-format
msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
msgstr ""
-#: keystone/common/sql/nova.py:133
+#: keystone/common/sql/nova.py:136
#, python-format
msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
msgstr ""
-#: keystone/identity/backends/kvs.py:250 keystone/identity/backends/kvs.py:259
-msgid "User not found in group"
-msgstr ""
-
-#: keystone/identity/backends/sql.py:425
+#: keystone/identity/controllers.py:952
#, python-format
-msgid "Cannot remove role that has not been granted, %s"
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:82
-#, python-format
-msgid "Expected dict or list: %s"
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
+msgid "User not found in group"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:681
+#: keystone/identity/backends/ldap.py:189
#, python-format
-msgid "Role %s not found"
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
msgstr ""
-#: keystone/identity/backends/ldap/core.py:898
+#: keystone/identity/backends/ldap.py:334
msgid "Changing Name not supported by LDAP"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:911
+#: keystone/identity/backends/ldap.py:347
#, python-format
msgid "User %(user_id)s is already a member of group %(group_id)s"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:954
-#, python-format
-msgid ""
-"Group member '%(user_dn)s' not found in '%(group_dn)s'. The user should "
-"be removed from the group. The user will be ignored."
-msgstr ""
-
#: keystone/openstack/common/policy.py:394
#, python-format
msgid "Failed to understand rule %(rule)s"
@@ -535,21 +729,56 @@ msgstr ""
msgid "Failed to understand rule %(rule)r"
msgstr ""
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
#: keystone/policy/backends/rules.py:93
#, python-format
msgid "enforce %(action)s: %(credentials)s"
msgstr ""
-#: keystone/token/controllers.py:465 keystone/token/controllers.py:468
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
msgid "Token does not belong to specified tenant."
msgstr ""
-#: keystone/token/controllers.py:475
-msgid "Non-default domain is not supported"
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
msgstr ""
-#: keystone/token/controllers.py:483
-msgid "Domain scoped token is not supported"
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
msgstr ""
#: keystone/token/backends/memcache.py:144
@@ -574,3 +803,54 @@ msgstr ""
msgid "Unable to add token to revocation list."
msgstr ""
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
+#~ msgid "User have no access to project"
+#~ msgstr ""
+
+#~ msgid "User have no access to domain"
+#~ msgstr ""
+
+#~ msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+#~ msgstr ""
+
diff --git a/keystone/locale/ms/LC_MESSAGES/keystone.po b/keystone/locale/ms/LC_MESSAGES/keystone.po
new file mode 100644
index 00000000..576761b9
--- /dev/null
+++ b/keystone/locale/ms/LC_MESSAGES/keystone.po
@@ -0,0 +1,847 @@
+# Malay translations for keystone.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the keystone project.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: Keystone\n"
+"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
+"PO-Revision-Date: 2013-07-29 22:01+0000\n"
+"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
+"Language-Team: Malay "
+"(http://www.transifex.com/projects/p/openstack/language/ms/)\n"
+"Plural-Forms: nplurals=1; plural=0\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: keystone/clean.py:23
+#, python-format
+msgid "%s cannot be empty."
+msgstr ""
+
+#: keystone/clean.py:25
+#, python-format
+msgid "%(property_name)s cannot be less than %(min_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:29
+#, python-format
+msgid "%(property_name)s should not be greater than %(max_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:36
+#, python-format
+msgid "%(property_name)s is not a %(display_expected_type)s"
+msgstr ""
+
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
+#: keystone/test.py:117
+#, python-format
+msgid "Failed to checkout %s"
+msgstr ""
+
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr ""
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr ""
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
+#, python-format
+msgid "Project is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
+#, python-format
+msgid "Domain is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
+#, python-format
+msgid "User is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:262
+msgid "Scoping to both domain and project is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:265
+msgid "Scoping to both domain and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:268
+msgid "Scoping to both project and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:353
+msgid "User not found"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
+#, python-format
+msgid "Unable to lookup user %s"
+msgstr ""
+
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
+msgstr ""
+
+#: keystone/catalog/core.py:38
+#, python-format
+msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s"
+msgstr ""
+
+#: keystone/catalog/core.py:43
+#, python-format
+msgid ""
+"Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing "
+"brackets ?)"
+msgstr ""
+
+#: keystone/catalog/core.py:49
+#, python-format
+msgid ""
+"Malformed endpoint %s - incomplete format (are you "
+"missing a type notifier ?)"
+msgstr ""
+
+#: keystone/catalog/backends/templated.py:109
+#, python-format
+msgid "Unable to open template file %s"
+msgstr ""
+
+#: keystone/common/cms.py:26
+#, python-format
+msgid "Verify error: %s"
+msgstr ""
+
+#: keystone/common/cms.py:118
+msgid ""
+"Signing error: Unable to load certificate - ensure you've configured PKI "
+"with 'keystone-manage pki_setup'"
+msgstr ""
+
+#: keystone/common/cms.py:122
+#, python-format
+msgid "Signing error: %s"
+msgstr ""
+
+#: keystone/common/config.py:89
+#, python-format
+msgid "Unable to locate specified logging config file: %s"
+msgstr ""
+
+#: keystone/common/config.py:107
+msgid "Invalid syslog facility"
+msgstr ""
+
+#: keystone/common/controller.py:18
+#, python-format
+msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
+msgstr ""
+
+#: keystone/common/controller.py:25
+msgid "RBAC: Invalid token"
+msgstr ""
+
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
+msgid "RBAC: Invalid user"
+msgstr ""
+
+#: keystone/common/controller.py:45
+msgid "RBAC: Proceeding without project"
+msgstr ""
+
+#: keystone/common/controller.py:65
+msgid "RBAC: Proceeding without tenant"
+msgstr ""
+
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
+msgid "RBAC: Bypassing authorization"
+msgstr ""
+
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
+msgid "RBAC: Authorization granted"
+msgstr ""
+
+#: keystone/common/controller.py:134
+#, python-format
+msgid "RBAC: Adding query filter params (%s)"
+msgstr ""
+
+#: keystone/common/controller.py:322
+msgid "Invalid token in normalize_domain_id"
+msgstr ""
+
+#: keystone/common/utils.py:233
+msgid ""
+"Error setting up the debug environment. Verify that the option --debug-"
+"url has the format <host>:<port> and that a debugger processes is "
+"listening on that port."
+msgstr ""
+
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
+#, python-format
+msgid "arg_dict: %s"
+msgstr ""
+
+#: keystone/common/wsgi.py:243
+#, python-format
+msgid "Authorization failed. %(exception)s from %(remote_addr)s"
+msgstr ""
+
+#: keystone/common/wsgi.py:487
+msgid "The resource could not be found."
+msgstr ""
+
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
+#, python-format
+msgid "Starting %(arg0)s on %(host)s:%(port)s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:113
+msgid "Server error"
+msgstr ""
+
+#: keystone/common/ldap/core.py:79
+#, python-format
+msgid "Invalid LDAP deref option: %s. Choose one of: "
+msgstr ""
+
+#: keystone/common/ldap/core.py:87
+#, python-format
+msgid "Invalid LDAP TLS certs option: %(option). Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:99
+#, python-format
+msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:189
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%s\". Format must be "
+"<ldap_attribute>:<keystone_attribute>"
+msgstr ""
+
+#: keystone/common/ldap/core.py:195
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%(item)s\". Value "
+"\"%(attr_map)s\" must use one of %(keys)s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
+#, python-format
+msgid "Duplicate name, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
+#, python-format
+msgid "Duplicate ID, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:294
+#, python-format
+msgid "LDAP %s create"
+msgstr ""
+
+#: keystone/common/ldap/core.py:372
+#, python-format
+msgid "LDAP %s update"
+msgstr ""
+
+#: keystone/common/ldap/core.py:405
+#, python-format
+msgid "LDAP %s delete"
+msgstr ""
+
+#: keystone/common/ldap/core.py:430
+#, python-format
+msgid "LDAP init: url=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:431
+#, python-format
+msgid ""
+"LDAP init: use_tls=%(use_tls)s\n"
+"tls_cacertfile=%(tls_cacertfile)s\n"
+"tls_cacertdir=%(tls_cacertdir)s\n"
+"tls_req_cert=%(tls_req_cert)s\n"
+"tls_avail=%(tls_avail)s\n"
+msgstr ""
+
+#: keystone/common/ldap/core.py:450
+msgid "Invalid TLS / LDAPS combination"
+msgstr ""
+
+#: keystone/common/ldap/core.py:454
+#, python-format
+msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available"
+msgstr ""
+
+#: keystone/common/ldap/core.py:464
+#, python-format
+msgid "tls_cacertfile %s not found or is not a file"
+msgstr ""
+
+#: keystone/common/ldap/core.py:476
+#, python-format
+msgid "tls_cacertdir %s not found or is not a directory"
+msgstr ""
+
+#: keystone/common/ldap/core.py:483
+#, python-format
+msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:497
+#, python-format
+msgid "LDAP bind: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:508
+#, python-format
+msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:514
+#, python-format
+msgid ""
+"LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, "
+"attrs=%(attrlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:567
+msgid ""
+"LDAP Server does not support paging. Disable paging in keystone.conf to "
+"avoid this message."
+msgstr ""
+
+#: keystone/common/ldap/core.py:584
+#, python-format
+msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:590
+#, python-format
+msgid "LDAP delete: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:595
+#, python-format
+msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:146
+#, python-format
+msgid "FakeLdap initialize url=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:156
+#, python-format
+msgid "FakeLdap bind dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:163
+#, python-format
+msgid "FakeLdap bind fail: dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:170
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:175
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s does not match"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:190
+#, python-format
+msgid "FakeLdap add item: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:193
+#, python-format
+msgid "FakeLdap add item failed: dn=%s is already in store."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:207 keystone/common/ldap/fakeldap.py:221
+#, python-format
+msgid "FakeLdap delete item: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:211 keystone/common/ldap/fakeldap.py:225
+#, python-format
+msgid "FakeLdap delete item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:240
+#, python-format
+msgid "FakeLdap modify item: dn=%(dn)s attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:245
+#, python-format
+msgid "FakeLdap modify item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:262
+#, python-format
+msgid "FakeLdap modify item failed: item has no attribute \"%s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:273
+#, python-format
+msgid ""
+"FakeLdap modify item failed: item has no attribute \"%(k)s\" with value "
+"\"%(v)s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:279
+#, python-format
+msgid "FakeLdap modify item failed: unknown command %s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:281
+#, python-format
+msgid "modify_s action %s not implemented"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:300
+#, python-format
+msgid "FakeLdap search at dn=%(dn)s scope=%(scope)s query=%(query)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:306
+msgid "FakeLdap search fail: dn not found for SCOPE_BASE"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:320
+#, python-format
+msgid "Search scope %s not implemented."
+msgstr ""
+
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
+#, python-format
+msgid "Got mysql server has gone away: %s"
+msgstr ""
+
+#: keystone/common/sql/legacy.py:188
+#, python-format
+msgid "Cannot migrate EC2 credential: %s"
+msgstr ""
+
+#: keystone/common/sql/migration.py:47
+msgid "version should be an integer"
+msgstr ""
+
+#: keystone/common/sql/nova.py:65
+#, python-format
+msgid "Create tenant %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:82
+#, python-format
+msgid "Create user %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:91
+#, python-format
+msgid "Add user %(user_id)s to tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:100
+#, python-format
+msgid "Ignoring existing role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:107
+#, python-format
+msgid "Create role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:117
+#, python-format
+msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:136
+#, python-format
+msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/identity/controllers.py:952
+#, python-format
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
+msgstr ""
+
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
+msgid "User not found in group"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:189
+#, python-format
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:334
+msgid "Changing Name not supported by LDAP"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:347
+#, python-format
+msgid "User %(user_id)s is already a member of group %(group_id)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:394
+#, python-format
+msgid "Failed to understand rule %(rule)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:404
+#, python-format
+msgid "No handler for matches of kind %s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:679
+#, python-format
+msgid "Failed to understand rule %(rule)r"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
+#: keystone/policy/backends/rules.py:93
+#, python-format
+msgid "enforce %(action)s: %(credentials)s"
+msgstr ""
+
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
+msgid "Token does not belong to specified tenant."
+msgstr ""
+
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
+msgstr ""
+
+#: keystone/token/backends/memcache.py:144
+#, python-format
+msgid ""
+"Successful set of token-index-list for user-key \"%(user_key)s\", "
+"#%(count)d records"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:154
+#, python-format
+msgid ""
+"Failed to set token-index-list for user-key \"%(user_key)s\". Attempt "
+"%(cas_retry)d of %(cas_retry_max)d"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:163
+msgid "Unable to add token user list"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:172
+msgid "Unable to add token to revocation list."
+msgstr ""
+
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
diff --git a/keystone/locale/nb/LC_MESSAGES/keystone.po b/keystone/locale/nb/LC_MESSAGES/keystone.po
new file mode 100644
index 00000000..d7a13243
--- /dev/null
+++ b/keystone/locale/nb/LC_MESSAGES/keystone.po
@@ -0,0 +1,847 @@
+# Norwegian Bokmål translations for keystone.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the keystone project.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: Keystone\n"
+"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
+"PO-Revision-Date: 2013-07-29 22:01+0000\n"
+"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
+"Language-Team: Norwegian Bokmål "
+"(http://www.transifex.com/projects/p/openstack/language/nb/)\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: keystone/clean.py:23
+#, python-format
+msgid "%s cannot be empty."
+msgstr ""
+
+#: keystone/clean.py:25
+#, python-format
+msgid "%(property_name)s cannot be less than %(min_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:29
+#, python-format
+msgid "%(property_name)s should not be greater than %(max_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:36
+#, python-format
+msgid "%(property_name)s is not a %(display_expected_type)s"
+msgstr ""
+
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
+#: keystone/test.py:117
+#, python-format
+msgid "Failed to checkout %s"
+msgstr ""
+
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr ""
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr ""
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
+#, python-format
+msgid "Project is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
+#, python-format
+msgid "Domain is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
+#, python-format
+msgid "User is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:262
+msgid "Scoping to both domain and project is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:265
+msgid "Scoping to both domain and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:268
+msgid "Scoping to both project and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:353
+msgid "User not found"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
+#, python-format
+msgid "Unable to lookup user %s"
+msgstr ""
+
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
+msgstr ""
+
+#: keystone/catalog/core.py:38
+#, python-format
+msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s"
+msgstr ""
+
+#: keystone/catalog/core.py:43
+#, python-format
+msgid ""
+"Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing "
+"brackets ?)"
+msgstr ""
+
+#: keystone/catalog/core.py:49
+#, python-format
+msgid ""
+"Malformed endpoint %s - incomplete format (are you "
+"missing a type notifier ?)"
+msgstr ""
+
+#: keystone/catalog/backends/templated.py:109
+#, python-format
+msgid "Unable to open template file %s"
+msgstr ""
+
+#: keystone/common/cms.py:26
+#, python-format
+msgid "Verify error: %s"
+msgstr ""
+
+#: keystone/common/cms.py:118
+msgid ""
+"Signing error: Unable to load certificate - ensure you've configured PKI "
+"with 'keystone-manage pki_setup'"
+msgstr ""
+
+#: keystone/common/cms.py:122
+#, python-format
+msgid "Signing error: %s"
+msgstr ""
+
+#: keystone/common/config.py:89
+#, python-format
+msgid "Unable to locate specified logging config file: %s"
+msgstr ""
+
+#: keystone/common/config.py:107
+msgid "Invalid syslog facility"
+msgstr ""
+
+#: keystone/common/controller.py:18
+#, python-format
+msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
+msgstr ""
+
+#: keystone/common/controller.py:25
+msgid "RBAC: Invalid token"
+msgstr ""
+
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
+msgid "RBAC: Invalid user"
+msgstr ""
+
+#: keystone/common/controller.py:45
+msgid "RBAC: Proceeding without project"
+msgstr ""
+
+#: keystone/common/controller.py:65
+msgid "RBAC: Proceeding without tenant"
+msgstr ""
+
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
+msgid "RBAC: Bypassing authorization"
+msgstr ""
+
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
+msgid "RBAC: Authorization granted"
+msgstr ""
+
+#: keystone/common/controller.py:134
+#, python-format
+msgid "RBAC: Adding query filter params (%s)"
+msgstr ""
+
+#: keystone/common/controller.py:322
+msgid "Invalid token in normalize_domain_id"
+msgstr ""
+
+#: keystone/common/utils.py:233
+msgid ""
+"Error setting up the debug environment. Verify that the option --debug-"
+"url has the format <host>:<port> and that a debugger processes is "
+"listening on that port."
+msgstr ""
+
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
+#, python-format
+msgid "arg_dict: %s"
+msgstr ""
+
+#: keystone/common/wsgi.py:243
+#, python-format
+msgid "Authorization failed. %(exception)s from %(remote_addr)s"
+msgstr ""
+
+#: keystone/common/wsgi.py:487
+msgid "The resource could not be found."
+msgstr ""
+
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
+#, python-format
+msgid "Starting %(arg0)s on %(host)s:%(port)s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:113
+msgid "Server error"
+msgstr ""
+
+#: keystone/common/ldap/core.py:79
+#, python-format
+msgid "Invalid LDAP deref option: %s. Choose one of: "
+msgstr ""
+
+#: keystone/common/ldap/core.py:87
+#, python-format
+msgid "Invalid LDAP TLS certs option: %(option). Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:99
+#, python-format
+msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:189
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%s\". Format must be "
+"<ldap_attribute>:<keystone_attribute>"
+msgstr ""
+
+#: keystone/common/ldap/core.py:195
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%(item)s\". Value "
+"\"%(attr_map)s\" must use one of %(keys)s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
+#, python-format
+msgid "Duplicate name, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
+#, python-format
+msgid "Duplicate ID, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:294
+#, python-format
+msgid "LDAP %s create"
+msgstr ""
+
+#: keystone/common/ldap/core.py:372
+#, python-format
+msgid "LDAP %s update"
+msgstr ""
+
+#: keystone/common/ldap/core.py:405
+#, python-format
+msgid "LDAP %s delete"
+msgstr ""
+
+#: keystone/common/ldap/core.py:430
+#, python-format
+msgid "LDAP init: url=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:431
+#, python-format
+msgid ""
+"LDAP init: use_tls=%(use_tls)s\n"
+"tls_cacertfile=%(tls_cacertfile)s\n"
+"tls_cacertdir=%(tls_cacertdir)s\n"
+"tls_req_cert=%(tls_req_cert)s\n"
+"tls_avail=%(tls_avail)s\n"
+msgstr ""
+
+#: keystone/common/ldap/core.py:450
+msgid "Invalid TLS / LDAPS combination"
+msgstr ""
+
+#: keystone/common/ldap/core.py:454
+#, python-format
+msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available"
+msgstr ""
+
+#: keystone/common/ldap/core.py:464
+#, python-format
+msgid "tls_cacertfile %s not found or is not a file"
+msgstr ""
+
+#: keystone/common/ldap/core.py:476
+#, python-format
+msgid "tls_cacertdir %s not found or is not a directory"
+msgstr ""
+
+#: keystone/common/ldap/core.py:483
+#, python-format
+msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:497
+#, python-format
+msgid "LDAP bind: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:508
+#, python-format
+msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:514
+#, python-format
+msgid ""
+"LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, "
+"attrs=%(attrlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:567
+msgid ""
+"LDAP Server does not support paging. Disable paging in keystone.conf to "
+"avoid this message."
+msgstr ""
+
+#: keystone/common/ldap/core.py:584
+#, python-format
+msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:590
+#, python-format
+msgid "LDAP delete: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:595
+#, python-format
+msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:146
+#, python-format
+msgid "FakeLdap initialize url=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:156
+#, python-format
+msgid "FakeLdap bind dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:163
+#, python-format
+msgid "FakeLdap bind fail: dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:170
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:175
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s does not match"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:190
+#, python-format
+msgid "FakeLdap add item: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:193
+#, python-format
+msgid "FakeLdap add item failed: dn=%s is already in store."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:207 keystone/common/ldap/fakeldap.py:221
+#, python-format
+msgid "FakeLdap delete item: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:211 keystone/common/ldap/fakeldap.py:225
+#, python-format
+msgid "FakeLdap delete item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:240
+#, python-format
+msgid "FakeLdap modify item: dn=%(dn)s attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:245
+#, python-format
+msgid "FakeLdap modify item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:262
+#, python-format
+msgid "FakeLdap modify item failed: item has no attribute \"%s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:273
+#, python-format
+msgid ""
+"FakeLdap modify item failed: item has no attribute \"%(k)s\" with value "
+"\"%(v)s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:279
+#, python-format
+msgid "FakeLdap modify item failed: unknown command %s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:281
+#, python-format
+msgid "modify_s action %s not implemented"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:300
+#, python-format
+msgid "FakeLdap search at dn=%(dn)s scope=%(scope)s query=%(query)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:306
+msgid "FakeLdap search fail: dn not found for SCOPE_BASE"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:320
+#, python-format
+msgid "Search scope %s not implemented."
+msgstr ""
+
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
+#, python-format
+msgid "Got mysql server has gone away: %s"
+msgstr ""
+
+#: keystone/common/sql/legacy.py:188
+#, python-format
+msgid "Cannot migrate EC2 credential: %s"
+msgstr ""
+
+#: keystone/common/sql/migration.py:47
+msgid "version should be an integer"
+msgstr ""
+
+#: keystone/common/sql/nova.py:65
+#, python-format
+msgid "Create tenant %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:82
+#, python-format
+msgid "Create user %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:91
+#, python-format
+msgid "Add user %(user_id)s to tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:100
+#, python-format
+msgid "Ignoring existing role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:107
+#, python-format
+msgid "Create role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:117
+#, python-format
+msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:136
+#, python-format
+msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/identity/controllers.py:952
+#, python-format
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
+msgstr ""
+
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
+msgid "User not found in group"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:189
+#, python-format
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:334
+msgid "Changing Name not supported by LDAP"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:347
+#, python-format
+msgid "User %(user_id)s is already a member of group %(group_id)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:394
+#, python-format
+msgid "Failed to understand rule %(rule)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:404
+#, python-format
+msgid "No handler for matches of kind %s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:679
+#, python-format
+msgid "Failed to understand rule %(rule)r"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
+#: keystone/policy/backends/rules.py:93
+#, python-format
+msgid "enforce %(action)s: %(credentials)s"
+msgstr ""
+
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
+msgid "Token does not belong to specified tenant."
+msgstr ""
+
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
+msgstr ""
+
+#: keystone/token/backends/memcache.py:144
+#, python-format
+msgid ""
+"Successful set of token-index-list for user-key \"%(user_key)s\", "
+"#%(count)d records"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:154
+#, python-format
+msgid ""
+"Failed to set token-index-list for user-key \"%(user_key)s\". Attempt "
+"%(cas_retry)d of %(cas_retry_max)d"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:163
+msgid "Unable to add token user list"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:172
+msgid "Unable to add token to revocation list."
+msgstr ""
+
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
diff --git a/keystone/locale/nl_NL/LC_MESSAGES/keystone.po b/keystone/locale/nl_NL/LC_MESSAGES/keystone.po
new file mode 100644
index 00000000..6bbb3ab3
--- /dev/null
+++ b/keystone/locale/nl_NL/LC_MESSAGES/keystone.po
@@ -0,0 +1,847 @@
+# Dutch (Netherlands) translations for keystone.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the keystone project.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: Keystone\n"
+"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
+"PO-Revision-Date: 2013-07-29 22:01+0000\n"
+"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
+"Language-Team: Dutch (Netherlands) "
+"(http://www.transifex.com/projects/p/openstack/language/nl_NL/)\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: keystone/clean.py:23
+#, python-format
+msgid "%s cannot be empty."
+msgstr ""
+
+#: keystone/clean.py:25
+#, python-format
+msgid "%(property_name)s cannot be less than %(min_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:29
+#, python-format
+msgid "%(property_name)s should not be greater than %(max_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:36
+#, python-format
+msgid "%(property_name)s is not a %(display_expected_type)s"
+msgstr ""
+
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
+#: keystone/test.py:117
+#, python-format
+msgid "Failed to checkout %s"
+msgstr ""
+
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr ""
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr ""
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
+#, python-format
+msgid "Project is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
+#, python-format
+msgid "Domain is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
+#, python-format
+msgid "User is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:262
+msgid "Scoping to both domain and project is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:265
+msgid "Scoping to both domain and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:268
+msgid "Scoping to both project and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:353
+msgid "User not found"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
+#, python-format
+msgid "Unable to lookup user %s"
+msgstr ""
+
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
+msgstr ""
+
+#: keystone/catalog/core.py:38
+#, python-format
+msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s"
+msgstr ""
+
+#: keystone/catalog/core.py:43
+#, python-format
+msgid ""
+"Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing "
+"brackets ?)"
+msgstr ""
+
+#: keystone/catalog/core.py:49
+#, python-format
+msgid ""
+"Malformed endpoint %s - incomplete format (are you "
+"missing a type notifier ?)"
+msgstr ""
+
+#: keystone/catalog/backends/templated.py:109
+#, python-format
+msgid "Unable to open template file %s"
+msgstr ""
+
+#: keystone/common/cms.py:26
+#, python-format
+msgid "Verify error: %s"
+msgstr ""
+
+#: keystone/common/cms.py:118
+msgid ""
+"Signing error: Unable to load certificate - ensure you've configured PKI "
+"with 'keystone-manage pki_setup'"
+msgstr ""
+
+#: keystone/common/cms.py:122
+#, python-format
+msgid "Signing error: %s"
+msgstr ""
+
+#: keystone/common/config.py:89
+#, python-format
+msgid "Unable to locate specified logging config file: %s"
+msgstr ""
+
+#: keystone/common/config.py:107
+msgid "Invalid syslog facility"
+msgstr ""
+
+#: keystone/common/controller.py:18
+#, python-format
+msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
+msgstr ""
+
+#: keystone/common/controller.py:25
+msgid "RBAC: Invalid token"
+msgstr ""
+
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
+msgid "RBAC: Invalid user"
+msgstr ""
+
+#: keystone/common/controller.py:45
+msgid "RBAC: Proceeding without project"
+msgstr ""
+
+#: keystone/common/controller.py:65
+msgid "RBAC: Proceeding without tenant"
+msgstr ""
+
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
+msgid "RBAC: Bypassing authorization"
+msgstr ""
+
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
+msgid "RBAC: Authorization granted"
+msgstr ""
+
+#: keystone/common/controller.py:134
+#, python-format
+msgid "RBAC: Adding query filter params (%s)"
+msgstr ""
+
+#: keystone/common/controller.py:322
+msgid "Invalid token in normalize_domain_id"
+msgstr ""
+
+#: keystone/common/utils.py:233
+msgid ""
+"Error setting up the debug environment. Verify that the option --debug-"
+"url has the format <host>:<port> and that a debugger processes is "
+"listening on that port."
+msgstr ""
+
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
+#, python-format
+msgid "arg_dict: %s"
+msgstr ""
+
+#: keystone/common/wsgi.py:243
+#, python-format
+msgid "Authorization failed. %(exception)s from %(remote_addr)s"
+msgstr ""
+
+#: keystone/common/wsgi.py:487
+msgid "The resource could not be found."
+msgstr ""
+
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
+#, python-format
+msgid "Starting %(arg0)s on %(host)s:%(port)s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:113
+msgid "Server error"
+msgstr ""
+
+#: keystone/common/ldap/core.py:79
+#, python-format
+msgid "Invalid LDAP deref option: %s. Choose one of: "
+msgstr ""
+
+#: keystone/common/ldap/core.py:87
+#, python-format
+msgid "Invalid LDAP TLS certs option: %(option). Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:99
+#, python-format
+msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:189
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%s\". Format must be "
+"<ldap_attribute>:<keystone_attribute>"
+msgstr ""
+
+#: keystone/common/ldap/core.py:195
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%(item)s\". Value "
+"\"%(attr_map)s\" must use one of %(keys)s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
+#, python-format
+msgid "Duplicate name, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
+#, python-format
+msgid "Duplicate ID, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:294
+#, python-format
+msgid "LDAP %s create"
+msgstr ""
+
+#: keystone/common/ldap/core.py:372
+#, python-format
+msgid "LDAP %s update"
+msgstr ""
+
+#: keystone/common/ldap/core.py:405
+#, python-format
+msgid "LDAP %s delete"
+msgstr ""
+
+#: keystone/common/ldap/core.py:430
+#, python-format
+msgid "LDAP init: url=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:431
+#, python-format
+msgid ""
+"LDAP init: use_tls=%(use_tls)s\n"
+"tls_cacertfile=%(tls_cacertfile)s\n"
+"tls_cacertdir=%(tls_cacertdir)s\n"
+"tls_req_cert=%(tls_req_cert)s\n"
+"tls_avail=%(tls_avail)s\n"
+msgstr ""
+
+#: keystone/common/ldap/core.py:450
+msgid "Invalid TLS / LDAPS combination"
+msgstr ""
+
+#: keystone/common/ldap/core.py:454
+#, python-format
+msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available"
+msgstr ""
+
+#: keystone/common/ldap/core.py:464
+#, python-format
+msgid "tls_cacertfile %s not found or is not a file"
+msgstr ""
+
+#: keystone/common/ldap/core.py:476
+#, python-format
+msgid "tls_cacertdir %s not found or is not a directory"
+msgstr ""
+
+#: keystone/common/ldap/core.py:483
+#, python-format
+msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:497
+#, python-format
+msgid "LDAP bind: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:508
+#, python-format
+msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:514
+#, python-format
+msgid ""
+"LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, "
+"attrs=%(attrlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:567
+msgid ""
+"LDAP Server does not support paging. Disable paging in keystone.conf to "
+"avoid this message."
+msgstr ""
+
+#: keystone/common/ldap/core.py:584
+#, python-format
+msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:590
+#, python-format
+msgid "LDAP delete: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:595
+#, python-format
+msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:146
+#, python-format
+msgid "FakeLdap initialize url=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:156
+#, python-format
+msgid "FakeLdap bind dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:163
+#, python-format
+msgid "FakeLdap bind fail: dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:170
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:175
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s does not match"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:190
+#, python-format
+msgid "FakeLdap add item: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:193
+#, python-format
+msgid "FakeLdap add item failed: dn=%s is already in store."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:207 keystone/common/ldap/fakeldap.py:221
+#, python-format
+msgid "FakeLdap delete item: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:211 keystone/common/ldap/fakeldap.py:225
+#, python-format
+msgid "FakeLdap delete item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:240
+#, python-format
+msgid "FakeLdap modify item: dn=%(dn)s attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:245
+#, python-format
+msgid "FakeLdap modify item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:262
+#, python-format
+msgid "FakeLdap modify item failed: item has no attribute \"%s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:273
+#, python-format
+msgid ""
+"FakeLdap modify item failed: item has no attribute \"%(k)s\" with value "
+"\"%(v)s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:279
+#, python-format
+msgid "FakeLdap modify item failed: unknown command %s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:281
+#, python-format
+msgid "modify_s action %s not implemented"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:300
+#, python-format
+msgid "FakeLdap search at dn=%(dn)s scope=%(scope)s query=%(query)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:306
+msgid "FakeLdap search fail: dn not found for SCOPE_BASE"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:320
+#, python-format
+msgid "Search scope %s not implemented."
+msgstr ""
+
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
+#, python-format
+msgid "Got mysql server has gone away: %s"
+msgstr ""
+
+#: keystone/common/sql/legacy.py:188
+#, python-format
+msgid "Cannot migrate EC2 credential: %s"
+msgstr ""
+
+#: keystone/common/sql/migration.py:47
+msgid "version should be an integer"
+msgstr ""
+
+#: keystone/common/sql/nova.py:65
+#, python-format
+msgid "Create tenant %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:82
+#, python-format
+msgid "Create user %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:91
+#, python-format
+msgid "Add user %(user_id)s to tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:100
+#, python-format
+msgid "Ignoring existing role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:107
+#, python-format
+msgid "Create role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:117
+#, python-format
+msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:136
+#, python-format
+msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/identity/controllers.py:952
+#, python-format
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
+msgstr ""
+
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
+msgid "User not found in group"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:189
+#, python-format
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:334
+msgid "Changing Name not supported by LDAP"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:347
+#, python-format
+msgid "User %(user_id)s is already a member of group %(group_id)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:394
+#, python-format
+msgid "Failed to understand rule %(rule)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:404
+#, python-format
+msgid "No handler for matches of kind %s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:679
+#, python-format
+msgid "Failed to understand rule %(rule)r"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
+#: keystone/policy/backends/rules.py:93
+#, python-format
+msgid "enforce %(action)s: %(credentials)s"
+msgstr ""
+
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
+msgid "Token does not belong to specified tenant."
+msgstr ""
+
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
+msgstr ""
+
+#: keystone/token/backends/memcache.py:144
+#, python-format
+msgid ""
+"Successful set of token-index-list for user-key \"%(user_key)s\", "
+"#%(count)d records"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:154
+#, python-format
+msgid ""
+"Failed to set token-index-list for user-key \"%(user_key)s\". Attempt "
+"%(cas_retry)d of %(cas_retry_max)d"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:163
+msgid "Unable to add token user list"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:172
+msgid "Unable to add token to revocation list."
+msgstr ""
+
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
diff --git a/keystone/locale/pl_PL/LC_MESSAGES/keystone.po b/keystone/locale/pl_PL/LC_MESSAGES/keystone.po
new file mode 100644
index 00000000..1971b675
--- /dev/null
+++ b/keystone/locale/pl_PL/LC_MESSAGES/keystone.po
@@ -0,0 +1,857 @@
+# Polish (Poland) translations for keystone.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the keystone project.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: Keystone\n"
+"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
+"PO-Revision-Date: 2013-06-28 06:06+0000\n"
+"Last-Translator: daisy.ycguo <daisy.ycguo@gmail.com>\n"
+"Language-Team: Polish (Poland) "
+"(http://www.transifex.com/projects/p/openstack/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"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: keystone/clean.py:23
+#, python-format
+msgid "%s cannot be empty."
+msgstr ""
+
+#: keystone/clean.py:25
+#, python-format
+msgid "%(property_name)s cannot be less than %(min_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:29
+#, python-format
+msgid "%(property_name)s should not be greater than %(max_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:36
+#, python-format
+msgid "%(property_name)s is not a %(display_expected_type)s"
+msgstr ""
+
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
+#: keystone/test.py:117
+#, python-format
+msgid "Failed to checkout %s"
+msgstr ""
+
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr ""
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr ""
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
+#, python-format
+msgid "Project is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
+#, python-format
+msgid "Domain is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
+#, python-format
+msgid "User is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:262
+msgid "Scoping to both domain and project is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:265
+msgid "Scoping to both domain and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:268
+msgid "Scoping to both project and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:353
+msgid "User not found"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
+#, python-format
+msgid "Unable to lookup user %s"
+msgstr ""
+
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
+msgstr ""
+
+#: keystone/catalog/core.py:38
+#, python-format
+msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s"
+msgstr ""
+
+#: keystone/catalog/core.py:43
+#, python-format
+msgid ""
+"Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing "
+"brackets ?)"
+msgstr ""
+
+#: keystone/catalog/core.py:49
+#, python-format
+msgid ""
+"Malformed endpoint %s - incomplete format (are you "
+"missing a type notifier ?)"
+msgstr ""
+
+#: keystone/catalog/backends/templated.py:109
+#, python-format
+msgid "Unable to open template file %s"
+msgstr ""
+
+#: keystone/common/cms.py:26
+#, python-format
+msgid "Verify error: %s"
+msgstr ""
+
+#: keystone/common/cms.py:118
+msgid ""
+"Signing error: Unable to load certificate - ensure you've configured PKI "
+"with 'keystone-manage pki_setup'"
+msgstr ""
+
+#: keystone/common/cms.py:122
+#, python-format
+msgid "Signing error: %s"
+msgstr ""
+
+#: keystone/common/config.py:89
+#, python-format
+msgid "Unable to locate specified logging config file: %s"
+msgstr ""
+
+#: keystone/common/config.py:107
+msgid "Invalid syslog facility"
+msgstr ""
+
+#: keystone/common/controller.py:18
+#, python-format
+msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
+msgstr ""
+
+#: keystone/common/controller.py:25
+msgid "RBAC: Invalid token"
+msgstr ""
+
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
+msgid "RBAC: Invalid user"
+msgstr ""
+
+#: keystone/common/controller.py:45
+msgid "RBAC: Proceeding without project"
+msgstr ""
+
+#: keystone/common/controller.py:65
+msgid "RBAC: Proceeding without tenant"
+msgstr ""
+
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
+msgid "RBAC: Bypassing authorization"
+msgstr ""
+
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
+msgid "RBAC: Authorization granted"
+msgstr ""
+
+#: keystone/common/controller.py:134
+#, python-format
+msgid "RBAC: Adding query filter params (%s)"
+msgstr ""
+
+#: keystone/common/controller.py:322
+msgid "Invalid token in normalize_domain_id"
+msgstr ""
+
+#: keystone/common/utils.py:233
+msgid ""
+"Error setting up the debug environment. Verify that the option --debug-"
+"url has the format <host>:<port> and that a debugger processes is "
+"listening on that port."
+msgstr ""
+
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
+#, python-format
+msgid "arg_dict: %s"
+msgstr ""
+
+#: keystone/common/wsgi.py:243
+#, python-format
+msgid "Authorization failed. %(exception)s from %(remote_addr)s"
+msgstr ""
+
+#: keystone/common/wsgi.py:487
+msgid "The resource could not be found."
+msgstr ""
+
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
+#, python-format
+msgid "Starting %(arg0)s on %(host)s:%(port)s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:113
+msgid "Server error"
+msgstr ""
+
+#: keystone/common/ldap/core.py:79
+#, python-format
+msgid "Invalid LDAP deref option: %s. Choose one of: "
+msgstr ""
+
+#: keystone/common/ldap/core.py:87
+#, python-format
+msgid "Invalid LDAP TLS certs option: %(option). Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:99
+#, python-format
+msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:189
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%s\". Format must be "
+"<ldap_attribute>:<keystone_attribute>"
+msgstr ""
+
+#: keystone/common/ldap/core.py:195
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%(item)s\". Value "
+"\"%(attr_map)s\" must use one of %(keys)s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
+#, python-format
+msgid "Duplicate name, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
+#, python-format
+msgid "Duplicate ID, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:294
+#, python-format
+msgid "LDAP %s create"
+msgstr ""
+
+#: keystone/common/ldap/core.py:372
+#, python-format
+msgid "LDAP %s update"
+msgstr ""
+
+#: keystone/common/ldap/core.py:405
+#, python-format
+msgid "LDAP %s delete"
+msgstr ""
+
+#: keystone/common/ldap/core.py:430
+#, python-format
+msgid "LDAP init: url=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:431
+#, python-format
+msgid ""
+"LDAP init: use_tls=%(use_tls)s\n"
+"tls_cacertfile=%(tls_cacertfile)s\n"
+"tls_cacertdir=%(tls_cacertdir)s\n"
+"tls_req_cert=%(tls_req_cert)s\n"
+"tls_avail=%(tls_avail)s\n"
+msgstr ""
+
+#: keystone/common/ldap/core.py:450
+msgid "Invalid TLS / LDAPS combination"
+msgstr ""
+
+#: keystone/common/ldap/core.py:454
+#, python-format
+msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available"
+msgstr ""
+
+#: keystone/common/ldap/core.py:464
+#, python-format
+msgid "tls_cacertfile %s not found or is not a file"
+msgstr ""
+
+#: keystone/common/ldap/core.py:476
+#, python-format
+msgid "tls_cacertdir %s not found or is not a directory"
+msgstr ""
+
+#: keystone/common/ldap/core.py:483
+#, python-format
+msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:497
+#, python-format
+msgid "LDAP bind: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:508
+#, python-format
+msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:514
+#, python-format
+msgid ""
+"LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, "
+"attrs=%(attrlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:567
+msgid ""
+"LDAP Server does not support paging. Disable paging in keystone.conf to "
+"avoid this message."
+msgstr ""
+
+#: keystone/common/ldap/core.py:584
+#, python-format
+msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:590
+#, python-format
+msgid "LDAP delete: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:595
+#, python-format
+msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:146
+#, python-format
+msgid "FakeLdap initialize url=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:156
+#, python-format
+msgid "FakeLdap bind dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:163
+#, python-format
+msgid "FakeLdap bind fail: dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:170
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:175
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s does not match"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:190
+#, python-format
+msgid "FakeLdap add item: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:193
+#, python-format
+msgid "FakeLdap add item failed: dn=%s is already in store."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:207 keystone/common/ldap/fakeldap.py:221
+#, python-format
+msgid "FakeLdap delete item: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:211 keystone/common/ldap/fakeldap.py:225
+#, python-format
+msgid "FakeLdap delete item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:240
+#, python-format
+msgid "FakeLdap modify item: dn=%(dn)s attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:245
+#, python-format
+msgid "FakeLdap modify item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:262
+#, python-format
+msgid "FakeLdap modify item failed: item has no attribute \"%s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:273
+#, python-format
+msgid ""
+"FakeLdap modify item failed: item has no attribute \"%(k)s\" with value "
+"\"%(v)s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:279
+#, python-format
+msgid "FakeLdap modify item failed: unknown command %s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:281
+#, python-format
+msgid "modify_s action %s not implemented"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:300
+#, python-format
+msgid "FakeLdap search at dn=%(dn)s scope=%(scope)s query=%(query)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:306
+msgid "FakeLdap search fail: dn not found for SCOPE_BASE"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:320
+#, python-format
+msgid "Search scope %s not implemented."
+msgstr ""
+
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
+#, python-format
+msgid "Got mysql server has gone away: %s"
+msgstr ""
+
+#: keystone/common/sql/legacy.py:188
+#, python-format
+msgid "Cannot migrate EC2 credential: %s"
+msgstr ""
+
+#: keystone/common/sql/migration.py:47
+msgid "version should be an integer"
+msgstr ""
+
+#: keystone/common/sql/nova.py:65
+#, python-format
+msgid "Create tenant %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:82
+#, python-format
+msgid "Create user %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:91
+#, python-format
+msgid "Add user %(user_id)s to tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:100
+#, python-format
+msgid "Ignoring existing role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:107
+#, python-format
+msgid "Create role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:117
+#, python-format
+msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:136
+#, python-format
+msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/identity/controllers.py:952
+#, python-format
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
+msgstr ""
+
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
+msgid "User not found in group"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:189
+#, python-format
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:334
+msgid "Changing Name not supported by LDAP"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:347
+#, python-format
+msgid "User %(user_id)s is already a member of group %(group_id)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:394
+#, python-format
+msgid "Failed to understand rule %(rule)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:404
+#, python-format
+msgid "No handler for matches of kind %s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:679
+#, python-format
+msgid "Failed to understand rule %(rule)r"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
+#: keystone/policy/backends/rules.py:93
+#, python-format
+msgid "enforce %(action)s: %(credentials)s"
+msgstr ""
+
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
+msgid "Token does not belong to specified tenant."
+msgstr ""
+
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
+msgstr ""
+
+#: keystone/token/backends/memcache.py:144
+#, python-format
+msgid ""
+"Successful set of token-index-list for user-key \"%(user_key)s\", "
+"#%(count)d records"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:154
+#, python-format
+msgid ""
+"Failed to set token-index-list for user-key \"%(user_key)s\". Attempt "
+"%(cas_retry)d of %(cas_retry_max)d"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:163
+msgid "Unable to add token user list"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:172
+msgid "Unable to add token to revocation list."
+msgstr ""
+
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
+#~ msgid "User have no access to project"
+#~ msgstr ""
+
+#~ msgid "User have no access to domain"
+#~ msgstr ""
+
+#~ msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+#~ msgstr ""
+
diff --git a/keystone/locale/pt/LC_MESSAGES/keystone.po b/keystone/locale/pt/LC_MESSAGES/keystone.po
new file mode 100644
index 00000000..7f09b091
--- /dev/null
+++ b/keystone/locale/pt/LC_MESSAGES/keystone.po
@@ -0,0 +1,847 @@
+# Portuguese translations for keystone.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the keystone project.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: Keystone\n"
+"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
+"PO-Revision-Date: 2013-07-29 22:01+0000\n"
+"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
+"Language-Team: Portuguese "
+"(http://www.transifex.com/projects/p/openstack/language/pt/)\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: keystone/clean.py:23
+#, python-format
+msgid "%s cannot be empty."
+msgstr ""
+
+#: keystone/clean.py:25
+#, python-format
+msgid "%(property_name)s cannot be less than %(min_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:29
+#, python-format
+msgid "%(property_name)s should not be greater than %(max_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:36
+#, python-format
+msgid "%(property_name)s is not a %(display_expected_type)s"
+msgstr ""
+
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
+#: keystone/test.py:117
+#, python-format
+msgid "Failed to checkout %s"
+msgstr ""
+
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr ""
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr ""
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
+#, python-format
+msgid "Project is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
+#, python-format
+msgid "Domain is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
+#, python-format
+msgid "User is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:262
+msgid "Scoping to both domain and project is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:265
+msgid "Scoping to both domain and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:268
+msgid "Scoping to both project and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:353
+msgid "User not found"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
+#, python-format
+msgid "Unable to lookup user %s"
+msgstr ""
+
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
+msgstr ""
+
+#: keystone/catalog/core.py:38
+#, python-format
+msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s"
+msgstr ""
+
+#: keystone/catalog/core.py:43
+#, python-format
+msgid ""
+"Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing "
+"brackets ?)"
+msgstr ""
+
+#: keystone/catalog/core.py:49
+#, python-format
+msgid ""
+"Malformed endpoint %s - incomplete format (are you "
+"missing a type notifier ?)"
+msgstr ""
+
+#: keystone/catalog/backends/templated.py:109
+#, python-format
+msgid "Unable to open template file %s"
+msgstr ""
+
+#: keystone/common/cms.py:26
+#, python-format
+msgid "Verify error: %s"
+msgstr ""
+
+#: keystone/common/cms.py:118
+msgid ""
+"Signing error: Unable to load certificate - ensure you've configured PKI "
+"with 'keystone-manage pki_setup'"
+msgstr ""
+
+#: keystone/common/cms.py:122
+#, python-format
+msgid "Signing error: %s"
+msgstr ""
+
+#: keystone/common/config.py:89
+#, python-format
+msgid "Unable to locate specified logging config file: %s"
+msgstr ""
+
+#: keystone/common/config.py:107
+msgid "Invalid syslog facility"
+msgstr ""
+
+#: keystone/common/controller.py:18
+#, python-format
+msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
+msgstr ""
+
+#: keystone/common/controller.py:25
+msgid "RBAC: Invalid token"
+msgstr ""
+
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
+msgid "RBAC: Invalid user"
+msgstr ""
+
+#: keystone/common/controller.py:45
+msgid "RBAC: Proceeding without project"
+msgstr ""
+
+#: keystone/common/controller.py:65
+msgid "RBAC: Proceeding without tenant"
+msgstr ""
+
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
+msgid "RBAC: Bypassing authorization"
+msgstr ""
+
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
+msgid "RBAC: Authorization granted"
+msgstr ""
+
+#: keystone/common/controller.py:134
+#, python-format
+msgid "RBAC: Adding query filter params (%s)"
+msgstr ""
+
+#: keystone/common/controller.py:322
+msgid "Invalid token in normalize_domain_id"
+msgstr ""
+
+#: keystone/common/utils.py:233
+msgid ""
+"Error setting up the debug environment. Verify that the option --debug-"
+"url has the format <host>:<port> and that a debugger processes is "
+"listening on that port."
+msgstr ""
+
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
+#, python-format
+msgid "arg_dict: %s"
+msgstr ""
+
+#: keystone/common/wsgi.py:243
+#, python-format
+msgid "Authorization failed. %(exception)s from %(remote_addr)s"
+msgstr ""
+
+#: keystone/common/wsgi.py:487
+msgid "The resource could not be found."
+msgstr ""
+
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
+#, python-format
+msgid "Starting %(arg0)s on %(host)s:%(port)s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:113
+msgid "Server error"
+msgstr ""
+
+#: keystone/common/ldap/core.py:79
+#, python-format
+msgid "Invalid LDAP deref option: %s. Choose one of: "
+msgstr ""
+
+#: keystone/common/ldap/core.py:87
+#, python-format
+msgid "Invalid LDAP TLS certs option: %(option). Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:99
+#, python-format
+msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:189
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%s\". Format must be "
+"<ldap_attribute>:<keystone_attribute>"
+msgstr ""
+
+#: keystone/common/ldap/core.py:195
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%(item)s\". Value "
+"\"%(attr_map)s\" must use one of %(keys)s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
+#, python-format
+msgid "Duplicate name, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
+#, python-format
+msgid "Duplicate ID, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:294
+#, python-format
+msgid "LDAP %s create"
+msgstr ""
+
+#: keystone/common/ldap/core.py:372
+#, python-format
+msgid "LDAP %s update"
+msgstr ""
+
+#: keystone/common/ldap/core.py:405
+#, python-format
+msgid "LDAP %s delete"
+msgstr ""
+
+#: keystone/common/ldap/core.py:430
+#, python-format
+msgid "LDAP init: url=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:431
+#, python-format
+msgid ""
+"LDAP init: use_tls=%(use_tls)s\n"
+"tls_cacertfile=%(tls_cacertfile)s\n"
+"tls_cacertdir=%(tls_cacertdir)s\n"
+"tls_req_cert=%(tls_req_cert)s\n"
+"tls_avail=%(tls_avail)s\n"
+msgstr ""
+
+#: keystone/common/ldap/core.py:450
+msgid "Invalid TLS / LDAPS combination"
+msgstr ""
+
+#: keystone/common/ldap/core.py:454
+#, python-format
+msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available"
+msgstr ""
+
+#: keystone/common/ldap/core.py:464
+#, python-format
+msgid "tls_cacertfile %s not found or is not a file"
+msgstr ""
+
+#: keystone/common/ldap/core.py:476
+#, python-format
+msgid "tls_cacertdir %s not found or is not a directory"
+msgstr ""
+
+#: keystone/common/ldap/core.py:483
+#, python-format
+msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:497
+#, python-format
+msgid "LDAP bind: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:508
+#, python-format
+msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:514
+#, python-format
+msgid ""
+"LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, "
+"attrs=%(attrlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:567
+msgid ""
+"LDAP Server does not support paging. Disable paging in keystone.conf to "
+"avoid this message."
+msgstr ""
+
+#: keystone/common/ldap/core.py:584
+#, python-format
+msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:590
+#, python-format
+msgid "LDAP delete: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:595
+#, python-format
+msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:146
+#, python-format
+msgid "FakeLdap initialize url=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:156
+#, python-format
+msgid "FakeLdap bind dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:163
+#, python-format
+msgid "FakeLdap bind fail: dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:170
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:175
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s does not match"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:190
+#, python-format
+msgid "FakeLdap add item: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:193
+#, python-format
+msgid "FakeLdap add item failed: dn=%s is already in store."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:207 keystone/common/ldap/fakeldap.py:221
+#, python-format
+msgid "FakeLdap delete item: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:211 keystone/common/ldap/fakeldap.py:225
+#, python-format
+msgid "FakeLdap delete item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:240
+#, python-format
+msgid "FakeLdap modify item: dn=%(dn)s attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:245
+#, python-format
+msgid "FakeLdap modify item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:262
+#, python-format
+msgid "FakeLdap modify item failed: item has no attribute \"%s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:273
+#, python-format
+msgid ""
+"FakeLdap modify item failed: item has no attribute \"%(k)s\" with value "
+"\"%(v)s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:279
+#, python-format
+msgid "FakeLdap modify item failed: unknown command %s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:281
+#, python-format
+msgid "modify_s action %s not implemented"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:300
+#, python-format
+msgid "FakeLdap search at dn=%(dn)s scope=%(scope)s query=%(query)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:306
+msgid "FakeLdap search fail: dn not found for SCOPE_BASE"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:320
+#, python-format
+msgid "Search scope %s not implemented."
+msgstr ""
+
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
+#, python-format
+msgid "Got mysql server has gone away: %s"
+msgstr ""
+
+#: keystone/common/sql/legacy.py:188
+#, python-format
+msgid "Cannot migrate EC2 credential: %s"
+msgstr ""
+
+#: keystone/common/sql/migration.py:47
+msgid "version should be an integer"
+msgstr ""
+
+#: keystone/common/sql/nova.py:65
+#, python-format
+msgid "Create tenant %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:82
+#, python-format
+msgid "Create user %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:91
+#, python-format
+msgid "Add user %(user_id)s to tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:100
+#, python-format
+msgid "Ignoring existing role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:107
+#, python-format
+msgid "Create role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:117
+#, python-format
+msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:136
+#, python-format
+msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/identity/controllers.py:952
+#, python-format
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
+msgstr ""
+
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
+msgid "User not found in group"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:189
+#, python-format
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:334
+msgid "Changing Name not supported by LDAP"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:347
+#, python-format
+msgid "User %(user_id)s is already a member of group %(group_id)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:394
+#, python-format
+msgid "Failed to understand rule %(rule)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:404
+#, python-format
+msgid "No handler for matches of kind %s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:679
+#, python-format
+msgid "Failed to understand rule %(rule)r"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
+#: keystone/policy/backends/rules.py:93
+#, python-format
+msgid "enforce %(action)s: %(credentials)s"
+msgstr ""
+
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
+msgid "Token does not belong to specified tenant."
+msgstr ""
+
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
+msgstr ""
+
+#: keystone/token/backends/memcache.py:144
+#, python-format
+msgid ""
+"Successful set of token-index-list for user-key \"%(user_key)s\", "
+"#%(count)d records"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:154
+#, python-format
+msgid ""
+"Failed to set token-index-list for user-key \"%(user_key)s\". Attempt "
+"%(cas_retry)d of %(cas_retry_max)d"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:163
+msgid "Unable to add token user list"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:172
+msgid "Unable to add token to revocation list."
+msgstr ""
+
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
diff --git a/keystone/locale/pt_BR/LC_MESSAGES/keystone.po b/keystone/locale/pt_BR/LC_MESSAGES/keystone.po
index 61f81246..c580894d 100644
--- a/keystone/locale/pt_BR/LC_MESSAGES/keystone.po
+++ b/keystone/locale/pt_BR/LC_MESSAGES/keystone.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Keystone\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2013-06-17 17:09+0000\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
"PO-Revision-Date: 2012-11-02 18:30+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Portuguese (Brazil) "
@@ -16,7 +16,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.6\n"
+"Generated-By: Babel 1.3\n"
#: keystone/clean.py:23
#, python-format
@@ -38,62 +38,224 @@ msgstr ""
msgid "%(property_name)s is not a %(display_expected_type)s"
msgstr ""
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
#: keystone/test.py:117
#, python-format
msgid "Failed to checkout %s"
msgstr ""
-#: keystone/auth/controllers.py:72
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr ""
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr ""
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
#, python-format
msgid "Project is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:78 keystone/auth/plugins/password.py:39
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
#, python-format
msgid "Domain is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:84 keystone/auth/plugins/password.py:45
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
#, python-format
msgid "User is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:265
+#: keystone/auth/controllers.py:262
msgid "Scoping to both domain and project is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:268
+#: keystone/auth/controllers.py:265
msgid "Scoping to both domain and trust is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:271
+#: keystone/auth/controllers.py:268
msgid "Scoping to both project and trust is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:333
-#, python-format
-msgid "Unable to lookup user %s"
-msgstr ""
-
-#: keystone/auth/controllers.py:363
+#: keystone/auth/controllers.py:353
msgid "User not found"
msgstr ""
-#: keystone/auth/token_factory.py:81
-msgid "User have no access to project"
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
msgstr ""
-#: keystone/auth/token_factory.py:96
-msgid "User have no access to domain"
-msgstr ""
-
-#: keystone/auth/token_factory.py:314 keystone/token/controllers.py:121
-msgid "Unable to sign token."
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
+#, python-format
+msgid "Unable to lookup user %s"
msgstr ""
-#: keystone/auth/token_factory.py:317 keystone/token/controllers.py:124
-#, python-format
-msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
msgstr ""
#: keystone/catalog/core.py:38
@@ -120,18 +282,18 @@ msgstr ""
msgid "Unable to open template file %s"
msgstr ""
-#: keystone/common/cms.py:42
+#: keystone/common/cms.py:26
#, python-format
msgid "Verify error: %s"
msgstr ""
-#: keystone/common/cms.py:134
+#: keystone/common/cms.py:118
msgid ""
"Signing error: Unable to load certificate - ensure you've configured PKI "
"with 'keystone-manage pki_setup'"
msgstr ""
-#: keystone/common/cms.py:138
+#: keystone/common/cms.py:122
#, python-format
msgid "Signing error: %s"
msgstr ""
@@ -150,31 +312,31 @@ msgstr ""
msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
msgstr ""
-#: keystone/common/controller.py:26
+#: keystone/common/controller.py:25
msgid "RBAC: Invalid token"
msgstr ""
-#: keystone/common/controller.py:36 keystone/common/controller.py:57
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
msgid "RBAC: Invalid user"
msgstr ""
-#: keystone/common/controller.py:42
+#: keystone/common/controller.py:45
msgid "RBAC: Proceeding without project"
msgstr ""
-#: keystone/common/controller.py:62
+#: keystone/common/controller.py:65
msgid "RBAC: Proceeding without tenant"
msgstr ""
-#: keystone/common/controller.py:92 keystone/common/controller.py:144
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
msgid "RBAC: Bypassing authorization"
msgstr ""
-#: keystone/common/controller.py:101 keystone/common/controller.py:142
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
msgid "RBAC: Authorization granted"
msgstr ""
-#: keystone/common/controller.py:131
+#: keystone/common/controller.py:134
#, python-format
msgid "RBAC: Adding query filter params (%s)"
msgstr ""
@@ -183,33 +345,69 @@ msgstr ""
msgid "Invalid token in normalize_domain_id"
msgstr ""
-#: keystone/common/utils.py:232
+#: keystone/common/utils.py:233
msgid ""
"Error setting up the debug environment. Verify that the option --debug-"
"url has the format <host>:<port> and that a debugger processes is "
"listening on that port."
msgstr ""
-#: keystone/common/wsgi.py:162
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
#, python-format
msgid "arg_dict: %s"
msgstr ""
-#: keystone/common/wsgi.py:186
+#: keystone/common/wsgi.py:243
#, python-format
msgid "Authorization failed. %(exception)s from %(remote_addr)s"
msgstr ""
-#: keystone/common/wsgi.py:429
+#: keystone/common/wsgi.py:487
msgid "The resource could not be found."
msgstr ""
-#: keystone/common/wsgi_server.py:72
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
#, python-format
msgid "Starting %(arg0)s on %(host)s:%(port)s"
msgstr ""
-#: keystone/common/wsgi_server.py:132
+#: keystone/common/environment/eventlet_server.py:113
msgid "Server error"
msgstr ""
@@ -242,13 +440,13 @@ msgid ""
"\"%(attr_map)s\" must use one of %(keys)s."
msgstr ""
-#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:596
-#: keystone/identity/backends/kvs.py:624
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
#, python-format
msgid "Duplicate name, %s."
msgstr ""
-#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:589
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
#, python-format
msgid "Duplicate ID, %s."
msgstr ""
@@ -436,12 +634,16 @@ msgstr ""
msgid "Search scope %s not implemented."
msgstr ""
-#: keystone/common/sql/core.py:205
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
#, python-format
msgid "Got mysql server has gone away: %s"
msgstr ""
-#: keystone/common/sql/legacy.py:180
+#: keystone/common/sql/legacy.py:188
#, python-format
msgid "Cannot migrate EC2 credential: %s"
msgstr ""
@@ -450,76 +652,68 @@ msgstr ""
msgid "version should be an integer"
msgstr ""
-#: keystone/common/sql/nova.py:62
+#: keystone/common/sql/nova.py:65
#, python-format
msgid "Create tenant %s"
msgstr ""
-#: keystone/common/sql/nova.py:79
+#: keystone/common/sql/nova.py:82
#, python-format
msgid "Create user %s"
msgstr ""
-#: keystone/common/sql/nova.py:88
+#: keystone/common/sql/nova.py:91
#, python-format
msgid "Add user %(user_id)s to tenant %(tenant_id)s"
msgstr ""
-#: keystone/common/sql/nova.py:97
+#: keystone/common/sql/nova.py:100
#, python-format
msgid "Ignoring existing role %s"
msgstr ""
-#: keystone/common/sql/nova.py:104
+#: keystone/common/sql/nova.py:107
#, python-format
msgid "Create role %s"
msgstr ""
-#: keystone/common/sql/nova.py:114
+#: keystone/common/sql/nova.py:117
#, python-format
msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
msgstr ""
-#: keystone/common/sql/nova.py:133
+#: keystone/common/sql/nova.py:136
#, python-format
msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
msgstr ""
-#: keystone/identity/backends/kvs.py:250 keystone/identity/backends/kvs.py:259
-msgid "User not found in group"
-msgstr ""
-
-#: keystone/identity/backends/sql.py:425
+#: keystone/identity/controllers.py:952
#, python-format
-msgid "Cannot remove role that has not been granted, %s"
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:82
-#, python-format
-msgid "Expected dict or list: %s"
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
+msgid "User not found in group"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:681
+#: keystone/identity/backends/ldap.py:189
#, python-format
-msgid "Role %s not found"
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
msgstr ""
-#: keystone/identity/backends/ldap/core.py:898
+#: keystone/identity/backends/ldap.py:334
msgid "Changing Name not supported by LDAP"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:911
+#: keystone/identity/backends/ldap.py:347
#, python-format
msgid "User %(user_id)s is already a member of group %(group_id)s"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:954
-#, python-format
-msgid ""
-"Group member '%(user_dn)s' not found in '%(group_dn)s'. The user should "
-"be removed from the group. The user will be ignored."
-msgstr ""
-
#: keystone/openstack/common/policy.py:394
#, python-format
msgid "Failed to understand rule %(rule)s"
@@ -535,21 +729,56 @@ msgstr ""
msgid "Failed to understand rule %(rule)r"
msgstr ""
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
#: keystone/policy/backends/rules.py:93
#, python-format
msgid "enforce %(action)s: %(credentials)s"
msgstr ""
-#: keystone/token/controllers.py:465 keystone/token/controllers.py:468
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
msgid "Token does not belong to specified tenant."
msgstr ""
-#: keystone/token/controllers.py:475
-msgid "Non-default domain is not supported"
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
msgstr ""
-#: keystone/token/controllers.py:483
-msgid "Domain scoped token is not supported"
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
msgstr ""
#: keystone/token/backends/memcache.py:144
@@ -574,3 +803,54 @@ msgstr ""
msgid "Unable to add token to revocation list."
msgstr ""
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
+#~ msgid "User have no access to project"
+#~ msgstr ""
+
+#~ msgid "User have no access to domain"
+#~ msgstr ""
+
+#~ msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+#~ msgstr ""
+
diff --git a/keystone/locale/ro/LC_MESSAGES/keystone.po b/keystone/locale/ro/LC_MESSAGES/keystone.po
index f09a1178..b55073b6 100644
--- a/keystone/locale/ro/LC_MESSAGES/keystone.po
+++ b/keystone/locale/ro/LC_MESSAGES/keystone.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Keystone\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2013-06-17 17:09+0000\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
"PO-Revision-Date: 2013-06-08 07:51+0000\n"
"Last-Translator: daisy.ycguo <daisy.ycguo@gmail.com>\n"
"Language-Team: Romanian "
@@ -17,7 +17,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.6\n"
+"Generated-By: Babel 1.3\n"
#: keystone/clean.py:23
#, python-format
@@ -39,62 +39,224 @@ msgstr ""
msgid "%(property_name)s is not a %(display_expected_type)s"
msgstr ""
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
#: keystone/test.py:117
#, python-format
msgid "Failed to checkout %s"
msgstr ""
-#: keystone/auth/controllers.py:72
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr ""
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr ""
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
#, python-format
msgid "Project is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:78 keystone/auth/plugins/password.py:39
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
#, python-format
msgid "Domain is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:84 keystone/auth/plugins/password.py:45
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
#, python-format
msgid "User is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:265
+#: keystone/auth/controllers.py:262
msgid "Scoping to both domain and project is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:268
+#: keystone/auth/controllers.py:265
msgid "Scoping to both domain and trust is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:271
+#: keystone/auth/controllers.py:268
msgid "Scoping to both project and trust is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:333
-#, python-format
-msgid "Unable to lookup user %s"
-msgstr ""
-
-#: keystone/auth/controllers.py:363
+#: keystone/auth/controllers.py:353
msgid "User not found"
msgstr ""
-#: keystone/auth/token_factory.py:81
-msgid "User have no access to project"
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
msgstr ""
-#: keystone/auth/token_factory.py:96
-msgid "User have no access to domain"
-msgstr ""
-
-#: keystone/auth/token_factory.py:314 keystone/token/controllers.py:121
-msgid "Unable to sign token."
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
+#, python-format
+msgid "Unable to lookup user %s"
msgstr ""
-#: keystone/auth/token_factory.py:317 keystone/token/controllers.py:124
-#, python-format
-msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
msgstr ""
#: keystone/catalog/core.py:38
@@ -121,18 +283,18 @@ msgstr ""
msgid "Unable to open template file %s"
msgstr ""
-#: keystone/common/cms.py:42
+#: keystone/common/cms.py:26
#, python-format
msgid "Verify error: %s"
msgstr ""
-#: keystone/common/cms.py:134
+#: keystone/common/cms.py:118
msgid ""
"Signing error: Unable to load certificate - ensure you've configured PKI "
"with 'keystone-manage pki_setup'"
msgstr ""
-#: keystone/common/cms.py:138
+#: keystone/common/cms.py:122
#, python-format
msgid "Signing error: %s"
msgstr ""
@@ -151,31 +313,31 @@ msgstr ""
msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
msgstr ""
-#: keystone/common/controller.py:26
+#: keystone/common/controller.py:25
msgid "RBAC: Invalid token"
msgstr ""
-#: keystone/common/controller.py:36 keystone/common/controller.py:57
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
msgid "RBAC: Invalid user"
msgstr ""
-#: keystone/common/controller.py:42
+#: keystone/common/controller.py:45
msgid "RBAC: Proceeding without project"
msgstr ""
-#: keystone/common/controller.py:62
+#: keystone/common/controller.py:65
msgid "RBAC: Proceeding without tenant"
msgstr ""
-#: keystone/common/controller.py:92 keystone/common/controller.py:144
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
msgid "RBAC: Bypassing authorization"
msgstr ""
-#: keystone/common/controller.py:101 keystone/common/controller.py:142
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
msgid "RBAC: Authorization granted"
msgstr ""
-#: keystone/common/controller.py:131
+#: keystone/common/controller.py:134
#, python-format
msgid "RBAC: Adding query filter params (%s)"
msgstr ""
@@ -184,33 +346,69 @@ msgstr ""
msgid "Invalid token in normalize_domain_id"
msgstr ""
-#: keystone/common/utils.py:232
+#: keystone/common/utils.py:233
msgid ""
"Error setting up the debug environment. Verify that the option --debug-"
"url has the format <host>:<port> and that a debugger processes is "
"listening on that port."
msgstr ""
-#: keystone/common/wsgi.py:162
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
#, python-format
msgid "arg_dict: %s"
msgstr ""
-#: keystone/common/wsgi.py:186
+#: keystone/common/wsgi.py:243
#, python-format
msgid "Authorization failed. %(exception)s from %(remote_addr)s"
msgstr ""
-#: keystone/common/wsgi.py:429
+#: keystone/common/wsgi.py:487
msgid "The resource could not be found."
msgstr ""
-#: keystone/common/wsgi_server.py:72
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
#, python-format
msgid "Starting %(arg0)s on %(host)s:%(port)s"
msgstr ""
-#: keystone/common/wsgi_server.py:132
+#: keystone/common/environment/eventlet_server.py:113
msgid "Server error"
msgstr ""
@@ -243,13 +441,13 @@ msgid ""
"\"%(attr_map)s\" must use one of %(keys)s."
msgstr ""
-#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:596
-#: keystone/identity/backends/kvs.py:624
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
#, python-format
msgid "Duplicate name, %s."
msgstr ""
-#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:589
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
#, python-format
msgid "Duplicate ID, %s."
msgstr ""
@@ -437,12 +635,16 @@ msgstr ""
msgid "Search scope %s not implemented."
msgstr ""
-#: keystone/common/sql/core.py:205
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
#, python-format
msgid "Got mysql server has gone away: %s"
msgstr ""
-#: keystone/common/sql/legacy.py:180
+#: keystone/common/sql/legacy.py:188
#, python-format
msgid "Cannot migrate EC2 credential: %s"
msgstr ""
@@ -451,76 +653,68 @@ msgstr ""
msgid "version should be an integer"
msgstr ""
-#: keystone/common/sql/nova.py:62
+#: keystone/common/sql/nova.py:65
#, python-format
msgid "Create tenant %s"
msgstr ""
-#: keystone/common/sql/nova.py:79
+#: keystone/common/sql/nova.py:82
#, python-format
msgid "Create user %s"
msgstr ""
-#: keystone/common/sql/nova.py:88
+#: keystone/common/sql/nova.py:91
#, python-format
msgid "Add user %(user_id)s to tenant %(tenant_id)s"
msgstr ""
-#: keystone/common/sql/nova.py:97
+#: keystone/common/sql/nova.py:100
#, python-format
msgid "Ignoring existing role %s"
msgstr ""
-#: keystone/common/sql/nova.py:104
+#: keystone/common/sql/nova.py:107
#, python-format
msgid "Create role %s"
msgstr ""
-#: keystone/common/sql/nova.py:114
+#: keystone/common/sql/nova.py:117
#, python-format
msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
msgstr ""
-#: keystone/common/sql/nova.py:133
+#: keystone/common/sql/nova.py:136
#, python-format
msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
msgstr ""
-#: keystone/identity/backends/kvs.py:250 keystone/identity/backends/kvs.py:259
-msgid "User not found in group"
-msgstr ""
-
-#: keystone/identity/backends/sql.py:425
+#: keystone/identity/controllers.py:952
#, python-format
-msgid "Cannot remove role that has not been granted, %s"
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:82
-#, python-format
-msgid "Expected dict or list: %s"
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
+msgid "User not found in group"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:681
+#: keystone/identity/backends/ldap.py:189
#, python-format
-msgid "Role %s not found"
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
msgstr ""
-#: keystone/identity/backends/ldap/core.py:898
+#: keystone/identity/backends/ldap.py:334
msgid "Changing Name not supported by LDAP"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:911
+#: keystone/identity/backends/ldap.py:347
#, python-format
msgid "User %(user_id)s is already a member of group %(group_id)s"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:954
-#, python-format
-msgid ""
-"Group member '%(user_dn)s' not found in '%(group_dn)s'. The user should "
-"be removed from the group. The user will be ignored."
-msgstr ""
-
#: keystone/openstack/common/policy.py:394
#, python-format
msgid "Failed to understand rule %(rule)s"
@@ -536,21 +730,56 @@ msgstr ""
msgid "Failed to understand rule %(rule)r"
msgstr ""
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
#: keystone/policy/backends/rules.py:93
#, python-format
msgid "enforce %(action)s: %(credentials)s"
msgstr ""
-#: keystone/token/controllers.py:465 keystone/token/controllers.py:468
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
msgid "Token does not belong to specified tenant."
msgstr ""
-#: keystone/token/controllers.py:475
-msgid "Non-default domain is not supported"
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
msgstr ""
-#: keystone/token/controllers.py:483
-msgid "Domain scoped token is not supported"
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
msgstr ""
#: keystone/token/backends/memcache.py:144
@@ -575,3 +804,54 @@ msgstr ""
msgid "Unable to add token to revocation list."
msgstr ""
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
+#~ msgid "User have no access to project"
+#~ msgstr ""
+
+#~ msgid "User have no access to domain"
+#~ msgstr ""
+
+#~ msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+#~ msgstr ""
+
diff --git a/keystone/locale/ru/LC_MESSAGES/keystone.po b/keystone/locale/ru/LC_MESSAGES/keystone.po
index cbc74358..db8fe633 100644
--- a/keystone/locale/ru/LC_MESSAGES/keystone.po
+++ b/keystone/locale/ru/LC_MESSAGES/keystone.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Keystone\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2013-06-17 17:09+0000\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
"PO-Revision-Date: 2013-05-17 16:06+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
"Language-Team: Russian "
@@ -17,7 +17,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.6\n"
+"Generated-By: Babel 1.3\n"
#: keystone/clean.py:23
#, python-format
@@ -39,62 +39,224 @@ msgstr ""
msgid "%(property_name)s is not a %(display_expected_type)s"
msgstr ""
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
#: keystone/test.py:117
#, python-format
msgid "Failed to checkout %s"
msgstr ""
-#: keystone/auth/controllers.py:72
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr ""
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr ""
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
#, python-format
msgid "Project is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:78 keystone/auth/plugins/password.py:39
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
#, python-format
msgid "Domain is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:84 keystone/auth/plugins/password.py:45
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
#, python-format
msgid "User is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:265
+#: keystone/auth/controllers.py:262
msgid "Scoping to both domain and project is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:268
+#: keystone/auth/controllers.py:265
msgid "Scoping to both domain and trust is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:271
+#: keystone/auth/controllers.py:268
msgid "Scoping to both project and trust is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:333
-#, python-format
-msgid "Unable to lookup user %s"
-msgstr ""
-
-#: keystone/auth/controllers.py:363
+#: keystone/auth/controllers.py:353
msgid "User not found"
msgstr ""
-#: keystone/auth/token_factory.py:81
-msgid "User have no access to project"
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
msgstr ""
-#: keystone/auth/token_factory.py:96
-msgid "User have no access to domain"
-msgstr ""
-
-#: keystone/auth/token_factory.py:314 keystone/token/controllers.py:121
-msgid "Unable to sign token."
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
+#, python-format
+msgid "Unable to lookup user %s"
msgstr ""
-#: keystone/auth/token_factory.py:317 keystone/token/controllers.py:124
-#, python-format
-msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
msgstr ""
#: keystone/catalog/core.py:38
@@ -121,18 +283,18 @@ msgstr ""
msgid "Unable to open template file %s"
msgstr ""
-#: keystone/common/cms.py:42
+#: keystone/common/cms.py:26
#, python-format
msgid "Verify error: %s"
msgstr ""
-#: keystone/common/cms.py:134
+#: keystone/common/cms.py:118
msgid ""
"Signing error: Unable to load certificate - ensure you've configured PKI "
"with 'keystone-manage pki_setup'"
msgstr ""
-#: keystone/common/cms.py:138
+#: keystone/common/cms.py:122
#, python-format
msgid "Signing error: %s"
msgstr ""
@@ -151,31 +313,31 @@ msgstr ""
msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
msgstr ""
-#: keystone/common/controller.py:26
+#: keystone/common/controller.py:25
msgid "RBAC: Invalid token"
msgstr ""
-#: keystone/common/controller.py:36 keystone/common/controller.py:57
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
msgid "RBAC: Invalid user"
msgstr ""
-#: keystone/common/controller.py:42
+#: keystone/common/controller.py:45
msgid "RBAC: Proceeding without project"
msgstr ""
-#: keystone/common/controller.py:62
+#: keystone/common/controller.py:65
msgid "RBAC: Proceeding without tenant"
msgstr ""
-#: keystone/common/controller.py:92 keystone/common/controller.py:144
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
msgid "RBAC: Bypassing authorization"
msgstr ""
-#: keystone/common/controller.py:101 keystone/common/controller.py:142
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
msgid "RBAC: Authorization granted"
msgstr ""
-#: keystone/common/controller.py:131
+#: keystone/common/controller.py:134
#, python-format
msgid "RBAC: Adding query filter params (%s)"
msgstr ""
@@ -184,33 +346,69 @@ msgstr ""
msgid "Invalid token in normalize_domain_id"
msgstr ""
-#: keystone/common/utils.py:232
+#: keystone/common/utils.py:233
msgid ""
"Error setting up the debug environment. Verify that the option --debug-"
"url has the format <host>:<port> and that a debugger processes is "
"listening on that port."
msgstr ""
-#: keystone/common/wsgi.py:162
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
#, python-format
msgid "arg_dict: %s"
msgstr ""
-#: keystone/common/wsgi.py:186
+#: keystone/common/wsgi.py:243
#, python-format
msgid "Authorization failed. %(exception)s from %(remote_addr)s"
msgstr ""
-#: keystone/common/wsgi.py:429
+#: keystone/common/wsgi.py:487
msgid "The resource could not be found."
msgstr ""
-#: keystone/common/wsgi_server.py:72
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
#, python-format
msgid "Starting %(arg0)s on %(host)s:%(port)s"
msgstr ""
-#: keystone/common/wsgi_server.py:132
+#: keystone/common/environment/eventlet_server.py:113
msgid "Server error"
msgstr ""
@@ -243,13 +441,13 @@ msgid ""
"\"%(attr_map)s\" must use one of %(keys)s."
msgstr ""
-#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:596
-#: keystone/identity/backends/kvs.py:624
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
#, python-format
msgid "Duplicate name, %s."
msgstr ""
-#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:589
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
#, python-format
msgid "Duplicate ID, %s."
msgstr ""
@@ -437,12 +635,16 @@ msgstr ""
msgid "Search scope %s not implemented."
msgstr ""
-#: keystone/common/sql/core.py:205
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
#, python-format
msgid "Got mysql server has gone away: %s"
msgstr ""
-#: keystone/common/sql/legacy.py:180
+#: keystone/common/sql/legacy.py:188
#, python-format
msgid "Cannot migrate EC2 credential: %s"
msgstr ""
@@ -451,76 +653,68 @@ msgstr ""
msgid "version should be an integer"
msgstr ""
-#: keystone/common/sql/nova.py:62
+#: keystone/common/sql/nova.py:65
#, python-format
msgid "Create tenant %s"
msgstr ""
-#: keystone/common/sql/nova.py:79
+#: keystone/common/sql/nova.py:82
#, python-format
msgid "Create user %s"
msgstr ""
-#: keystone/common/sql/nova.py:88
+#: keystone/common/sql/nova.py:91
#, python-format
msgid "Add user %(user_id)s to tenant %(tenant_id)s"
msgstr ""
-#: keystone/common/sql/nova.py:97
+#: keystone/common/sql/nova.py:100
#, python-format
msgid "Ignoring existing role %s"
msgstr ""
-#: keystone/common/sql/nova.py:104
+#: keystone/common/sql/nova.py:107
#, python-format
msgid "Create role %s"
msgstr ""
-#: keystone/common/sql/nova.py:114
+#: keystone/common/sql/nova.py:117
#, python-format
msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
msgstr ""
-#: keystone/common/sql/nova.py:133
+#: keystone/common/sql/nova.py:136
#, python-format
msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
msgstr ""
-#: keystone/identity/backends/kvs.py:250 keystone/identity/backends/kvs.py:259
-msgid "User not found in group"
-msgstr ""
-
-#: keystone/identity/backends/sql.py:425
+#: keystone/identity/controllers.py:952
#, python-format
-msgid "Cannot remove role that has not been granted, %s"
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:82
-#, python-format
-msgid "Expected dict or list: %s"
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
+msgid "User not found in group"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:681
+#: keystone/identity/backends/ldap.py:189
#, python-format
-msgid "Role %s not found"
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
msgstr ""
-#: keystone/identity/backends/ldap/core.py:898
+#: keystone/identity/backends/ldap.py:334
msgid "Changing Name not supported by LDAP"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:911
+#: keystone/identity/backends/ldap.py:347
#, python-format
msgid "User %(user_id)s is already a member of group %(group_id)s"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:954
-#, python-format
-msgid ""
-"Group member '%(user_dn)s' not found in '%(group_dn)s'. The user should "
-"be removed from the group. The user will be ignored."
-msgstr ""
-
#: keystone/openstack/common/policy.py:394
#, python-format
msgid "Failed to understand rule %(rule)s"
@@ -536,21 +730,56 @@ msgstr ""
msgid "Failed to understand rule %(rule)r"
msgstr ""
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
#: keystone/policy/backends/rules.py:93
#, python-format
msgid "enforce %(action)s: %(credentials)s"
msgstr ""
-#: keystone/token/controllers.py:465 keystone/token/controllers.py:468
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
msgid "Token does not belong to specified tenant."
msgstr ""
-#: keystone/token/controllers.py:475
-msgid "Non-default domain is not supported"
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
msgstr ""
-#: keystone/token/controllers.py:483
-msgid "Domain scoped token is not supported"
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
msgstr ""
#: keystone/token/backends/memcache.py:144
@@ -575,3 +804,54 @@ msgstr ""
msgid "Unable to add token to revocation list."
msgstr ""
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
+#~ msgid "User have no access to project"
+#~ msgstr ""
+
+#~ msgid "User have no access to domain"
+#~ msgstr ""
+
+#~ msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+#~ msgstr ""
+
diff --git a/keystone/locale/ru_RU/LC_MESSAGES/keystone.po b/keystone/locale/ru_RU/LC_MESSAGES/keystone.po
new file mode 100644
index 00000000..4782ae4a
--- /dev/null
+++ b/keystone/locale/ru_RU/LC_MESSAGES/keystone.po
@@ -0,0 +1,848 @@
+# Russian (Russia) translations for keystone.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the keystone project.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: Keystone\n"
+"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
+"PO-Revision-Date: 2013-07-29 22:01+0000\n"
+"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
+"Language-Team: Russian (Russia) "
+"(http://www.transifex.com/projects/p/openstack/language/ru_RU/)\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 1.3\n"
+
+#: keystone/clean.py:23
+#, python-format
+msgid "%s cannot be empty."
+msgstr ""
+
+#: keystone/clean.py:25
+#, python-format
+msgid "%(property_name)s cannot be less than %(min_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:29
+#, python-format
+msgid "%(property_name)s should not be greater than %(max_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:36
+#, python-format
+msgid "%(property_name)s is not a %(display_expected_type)s"
+msgstr ""
+
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
+#: keystone/test.py:117
+#, python-format
+msgid "Failed to checkout %s"
+msgstr ""
+
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr ""
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr ""
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
+#, python-format
+msgid "Project is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
+#, python-format
+msgid "Domain is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
+#, python-format
+msgid "User is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:262
+msgid "Scoping to both domain and project is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:265
+msgid "Scoping to both domain and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:268
+msgid "Scoping to both project and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:353
+msgid "User not found"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
+#, python-format
+msgid "Unable to lookup user %s"
+msgstr ""
+
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
+msgstr ""
+
+#: keystone/catalog/core.py:38
+#, python-format
+msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s"
+msgstr ""
+
+#: keystone/catalog/core.py:43
+#, python-format
+msgid ""
+"Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing "
+"brackets ?)"
+msgstr ""
+
+#: keystone/catalog/core.py:49
+#, python-format
+msgid ""
+"Malformed endpoint %s - incomplete format (are you "
+"missing a type notifier ?)"
+msgstr ""
+
+#: keystone/catalog/backends/templated.py:109
+#, python-format
+msgid "Unable to open template file %s"
+msgstr ""
+
+#: keystone/common/cms.py:26
+#, python-format
+msgid "Verify error: %s"
+msgstr ""
+
+#: keystone/common/cms.py:118
+msgid ""
+"Signing error: Unable to load certificate - ensure you've configured PKI "
+"with 'keystone-manage pki_setup'"
+msgstr ""
+
+#: keystone/common/cms.py:122
+#, python-format
+msgid "Signing error: %s"
+msgstr ""
+
+#: keystone/common/config.py:89
+#, python-format
+msgid "Unable to locate specified logging config file: %s"
+msgstr ""
+
+#: keystone/common/config.py:107
+msgid "Invalid syslog facility"
+msgstr ""
+
+#: keystone/common/controller.py:18
+#, python-format
+msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
+msgstr ""
+
+#: keystone/common/controller.py:25
+msgid "RBAC: Invalid token"
+msgstr ""
+
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
+msgid "RBAC: Invalid user"
+msgstr ""
+
+#: keystone/common/controller.py:45
+msgid "RBAC: Proceeding without project"
+msgstr ""
+
+#: keystone/common/controller.py:65
+msgid "RBAC: Proceeding without tenant"
+msgstr ""
+
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
+msgid "RBAC: Bypassing authorization"
+msgstr ""
+
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
+msgid "RBAC: Authorization granted"
+msgstr ""
+
+#: keystone/common/controller.py:134
+#, python-format
+msgid "RBAC: Adding query filter params (%s)"
+msgstr ""
+
+#: keystone/common/controller.py:322
+msgid "Invalid token in normalize_domain_id"
+msgstr ""
+
+#: keystone/common/utils.py:233
+msgid ""
+"Error setting up the debug environment. Verify that the option --debug-"
+"url has the format <host>:<port> and that a debugger processes is "
+"listening on that port."
+msgstr ""
+
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
+#, python-format
+msgid "arg_dict: %s"
+msgstr ""
+
+#: keystone/common/wsgi.py:243
+#, python-format
+msgid "Authorization failed. %(exception)s from %(remote_addr)s"
+msgstr ""
+
+#: keystone/common/wsgi.py:487
+msgid "The resource could not be found."
+msgstr ""
+
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
+#, python-format
+msgid "Starting %(arg0)s on %(host)s:%(port)s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:113
+msgid "Server error"
+msgstr ""
+
+#: keystone/common/ldap/core.py:79
+#, python-format
+msgid "Invalid LDAP deref option: %s. Choose one of: "
+msgstr ""
+
+#: keystone/common/ldap/core.py:87
+#, python-format
+msgid "Invalid LDAP TLS certs option: %(option). Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:99
+#, python-format
+msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:189
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%s\". Format must be "
+"<ldap_attribute>:<keystone_attribute>"
+msgstr ""
+
+#: keystone/common/ldap/core.py:195
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%(item)s\". Value "
+"\"%(attr_map)s\" must use one of %(keys)s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
+#, python-format
+msgid "Duplicate name, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
+#, python-format
+msgid "Duplicate ID, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:294
+#, python-format
+msgid "LDAP %s create"
+msgstr ""
+
+#: keystone/common/ldap/core.py:372
+#, python-format
+msgid "LDAP %s update"
+msgstr ""
+
+#: keystone/common/ldap/core.py:405
+#, python-format
+msgid "LDAP %s delete"
+msgstr ""
+
+#: keystone/common/ldap/core.py:430
+#, python-format
+msgid "LDAP init: url=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:431
+#, python-format
+msgid ""
+"LDAP init: use_tls=%(use_tls)s\n"
+"tls_cacertfile=%(tls_cacertfile)s\n"
+"tls_cacertdir=%(tls_cacertdir)s\n"
+"tls_req_cert=%(tls_req_cert)s\n"
+"tls_avail=%(tls_avail)s\n"
+msgstr ""
+
+#: keystone/common/ldap/core.py:450
+msgid "Invalid TLS / LDAPS combination"
+msgstr ""
+
+#: keystone/common/ldap/core.py:454
+#, python-format
+msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available"
+msgstr ""
+
+#: keystone/common/ldap/core.py:464
+#, python-format
+msgid "tls_cacertfile %s not found or is not a file"
+msgstr ""
+
+#: keystone/common/ldap/core.py:476
+#, python-format
+msgid "tls_cacertdir %s not found or is not a directory"
+msgstr ""
+
+#: keystone/common/ldap/core.py:483
+#, python-format
+msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:497
+#, python-format
+msgid "LDAP bind: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:508
+#, python-format
+msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:514
+#, python-format
+msgid ""
+"LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, "
+"attrs=%(attrlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:567
+msgid ""
+"LDAP Server does not support paging. Disable paging in keystone.conf to "
+"avoid this message."
+msgstr ""
+
+#: keystone/common/ldap/core.py:584
+#, python-format
+msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:590
+#, python-format
+msgid "LDAP delete: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:595
+#, python-format
+msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:146
+#, python-format
+msgid "FakeLdap initialize url=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:156
+#, python-format
+msgid "FakeLdap bind dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:163
+#, python-format
+msgid "FakeLdap bind fail: dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:170
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:175
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s does not match"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:190
+#, python-format
+msgid "FakeLdap add item: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:193
+#, python-format
+msgid "FakeLdap add item failed: dn=%s is already in store."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:207 keystone/common/ldap/fakeldap.py:221
+#, python-format
+msgid "FakeLdap delete item: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:211 keystone/common/ldap/fakeldap.py:225
+#, python-format
+msgid "FakeLdap delete item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:240
+#, python-format
+msgid "FakeLdap modify item: dn=%(dn)s attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:245
+#, python-format
+msgid "FakeLdap modify item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:262
+#, python-format
+msgid "FakeLdap modify item failed: item has no attribute \"%s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:273
+#, python-format
+msgid ""
+"FakeLdap modify item failed: item has no attribute \"%(k)s\" with value "
+"\"%(v)s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:279
+#, python-format
+msgid "FakeLdap modify item failed: unknown command %s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:281
+#, python-format
+msgid "modify_s action %s not implemented"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:300
+#, python-format
+msgid "FakeLdap search at dn=%(dn)s scope=%(scope)s query=%(query)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:306
+msgid "FakeLdap search fail: dn not found for SCOPE_BASE"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:320
+#, python-format
+msgid "Search scope %s not implemented."
+msgstr ""
+
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
+#, python-format
+msgid "Got mysql server has gone away: %s"
+msgstr ""
+
+#: keystone/common/sql/legacy.py:188
+#, python-format
+msgid "Cannot migrate EC2 credential: %s"
+msgstr ""
+
+#: keystone/common/sql/migration.py:47
+msgid "version should be an integer"
+msgstr ""
+
+#: keystone/common/sql/nova.py:65
+#, python-format
+msgid "Create tenant %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:82
+#, python-format
+msgid "Create user %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:91
+#, python-format
+msgid "Add user %(user_id)s to tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:100
+#, python-format
+msgid "Ignoring existing role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:107
+#, python-format
+msgid "Create role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:117
+#, python-format
+msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:136
+#, python-format
+msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/identity/controllers.py:952
+#, python-format
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
+msgstr ""
+
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
+msgid "User not found in group"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:189
+#, python-format
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:334
+msgid "Changing Name not supported by LDAP"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:347
+#, python-format
+msgid "User %(user_id)s is already a member of group %(group_id)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:394
+#, python-format
+msgid "Failed to understand rule %(rule)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:404
+#, python-format
+msgid "No handler for matches of kind %s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:679
+#, python-format
+msgid "Failed to understand rule %(rule)r"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
+#: keystone/policy/backends/rules.py:93
+#, python-format
+msgid "enforce %(action)s: %(credentials)s"
+msgstr ""
+
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
+msgid "Token does not belong to specified tenant."
+msgstr ""
+
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
+msgstr ""
+
+#: keystone/token/backends/memcache.py:144
+#, python-format
+msgid ""
+"Successful set of token-index-list for user-key \"%(user_key)s\", "
+"#%(count)d records"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:154
+#, python-format
+msgid ""
+"Failed to set token-index-list for user-key \"%(user_key)s\". Attempt "
+"%(cas_retry)d of %(cas_retry_max)d"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:163
+msgid "Unable to add token user list"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:172
+msgid "Unable to add token to revocation list."
+msgstr ""
+
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
diff --git a/keystone/locale/sl_SI/LC_MESSAGES/keystone.po b/keystone/locale/sl_SI/LC_MESSAGES/keystone.po
new file mode 100644
index 00000000..8c044ca8
--- /dev/null
+++ b/keystone/locale/sl_SI/LC_MESSAGES/keystone.po
@@ -0,0 +1,857 @@
+# Slovenian (Slovenia) translations for keystone.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the keystone project.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: Keystone\n"
+"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
+"PO-Revision-Date: 2013-06-28 06:06+0000\n"
+"Last-Translator: daisy.ycguo <daisy.ycguo@gmail.com>\n"
+"Language-Team: Slovenian (Slovenia) "
+"(http://www.transifex.com/projects/p/openstack/language/sl_SI/)\n"
+"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 "
+"|| n%100==4 ? 2 : 3)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: keystone/clean.py:23
+#, python-format
+msgid "%s cannot be empty."
+msgstr ""
+
+#: keystone/clean.py:25
+#, python-format
+msgid "%(property_name)s cannot be less than %(min_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:29
+#, python-format
+msgid "%(property_name)s should not be greater than %(max_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:36
+#, python-format
+msgid "%(property_name)s is not a %(display_expected_type)s"
+msgstr ""
+
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
+#: keystone/test.py:117
+#, python-format
+msgid "Failed to checkout %s"
+msgstr ""
+
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr ""
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr ""
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
+#, python-format
+msgid "Project is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
+#, python-format
+msgid "Domain is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
+#, python-format
+msgid "User is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:262
+msgid "Scoping to both domain and project is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:265
+msgid "Scoping to both domain and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:268
+msgid "Scoping to both project and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:353
+msgid "User not found"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
+#, python-format
+msgid "Unable to lookup user %s"
+msgstr ""
+
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
+msgstr ""
+
+#: keystone/catalog/core.py:38
+#, python-format
+msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s"
+msgstr ""
+
+#: keystone/catalog/core.py:43
+#, python-format
+msgid ""
+"Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing "
+"brackets ?)"
+msgstr ""
+
+#: keystone/catalog/core.py:49
+#, python-format
+msgid ""
+"Malformed endpoint %s - incomplete format (are you "
+"missing a type notifier ?)"
+msgstr ""
+
+#: keystone/catalog/backends/templated.py:109
+#, python-format
+msgid "Unable to open template file %s"
+msgstr ""
+
+#: keystone/common/cms.py:26
+#, python-format
+msgid "Verify error: %s"
+msgstr ""
+
+#: keystone/common/cms.py:118
+msgid ""
+"Signing error: Unable to load certificate - ensure you've configured PKI "
+"with 'keystone-manage pki_setup'"
+msgstr ""
+
+#: keystone/common/cms.py:122
+#, python-format
+msgid "Signing error: %s"
+msgstr ""
+
+#: keystone/common/config.py:89
+#, python-format
+msgid "Unable to locate specified logging config file: %s"
+msgstr ""
+
+#: keystone/common/config.py:107
+msgid "Invalid syslog facility"
+msgstr ""
+
+#: keystone/common/controller.py:18
+#, python-format
+msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
+msgstr ""
+
+#: keystone/common/controller.py:25
+msgid "RBAC: Invalid token"
+msgstr ""
+
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
+msgid "RBAC: Invalid user"
+msgstr ""
+
+#: keystone/common/controller.py:45
+msgid "RBAC: Proceeding without project"
+msgstr ""
+
+#: keystone/common/controller.py:65
+msgid "RBAC: Proceeding without tenant"
+msgstr ""
+
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
+msgid "RBAC: Bypassing authorization"
+msgstr ""
+
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
+msgid "RBAC: Authorization granted"
+msgstr ""
+
+#: keystone/common/controller.py:134
+#, python-format
+msgid "RBAC: Adding query filter params (%s)"
+msgstr ""
+
+#: keystone/common/controller.py:322
+msgid "Invalid token in normalize_domain_id"
+msgstr ""
+
+#: keystone/common/utils.py:233
+msgid ""
+"Error setting up the debug environment. Verify that the option --debug-"
+"url has the format <host>:<port> and that a debugger processes is "
+"listening on that port."
+msgstr ""
+
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
+#, python-format
+msgid "arg_dict: %s"
+msgstr ""
+
+#: keystone/common/wsgi.py:243
+#, python-format
+msgid "Authorization failed. %(exception)s from %(remote_addr)s"
+msgstr ""
+
+#: keystone/common/wsgi.py:487
+msgid "The resource could not be found."
+msgstr ""
+
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
+#, python-format
+msgid "Starting %(arg0)s on %(host)s:%(port)s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:113
+msgid "Server error"
+msgstr ""
+
+#: keystone/common/ldap/core.py:79
+#, python-format
+msgid "Invalid LDAP deref option: %s. Choose one of: "
+msgstr ""
+
+#: keystone/common/ldap/core.py:87
+#, python-format
+msgid "Invalid LDAP TLS certs option: %(option). Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:99
+#, python-format
+msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:189
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%s\". Format must be "
+"<ldap_attribute>:<keystone_attribute>"
+msgstr ""
+
+#: keystone/common/ldap/core.py:195
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%(item)s\". Value "
+"\"%(attr_map)s\" must use one of %(keys)s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
+#, python-format
+msgid "Duplicate name, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
+#, python-format
+msgid "Duplicate ID, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:294
+#, python-format
+msgid "LDAP %s create"
+msgstr ""
+
+#: keystone/common/ldap/core.py:372
+#, python-format
+msgid "LDAP %s update"
+msgstr ""
+
+#: keystone/common/ldap/core.py:405
+#, python-format
+msgid "LDAP %s delete"
+msgstr ""
+
+#: keystone/common/ldap/core.py:430
+#, python-format
+msgid "LDAP init: url=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:431
+#, python-format
+msgid ""
+"LDAP init: use_tls=%(use_tls)s\n"
+"tls_cacertfile=%(tls_cacertfile)s\n"
+"tls_cacertdir=%(tls_cacertdir)s\n"
+"tls_req_cert=%(tls_req_cert)s\n"
+"tls_avail=%(tls_avail)s\n"
+msgstr ""
+
+#: keystone/common/ldap/core.py:450
+msgid "Invalid TLS / LDAPS combination"
+msgstr ""
+
+#: keystone/common/ldap/core.py:454
+#, python-format
+msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available"
+msgstr ""
+
+#: keystone/common/ldap/core.py:464
+#, python-format
+msgid "tls_cacertfile %s not found or is not a file"
+msgstr ""
+
+#: keystone/common/ldap/core.py:476
+#, python-format
+msgid "tls_cacertdir %s not found or is not a directory"
+msgstr ""
+
+#: keystone/common/ldap/core.py:483
+#, python-format
+msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:497
+#, python-format
+msgid "LDAP bind: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:508
+#, python-format
+msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:514
+#, python-format
+msgid ""
+"LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, "
+"attrs=%(attrlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:567
+msgid ""
+"LDAP Server does not support paging. Disable paging in keystone.conf to "
+"avoid this message."
+msgstr ""
+
+#: keystone/common/ldap/core.py:584
+#, python-format
+msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:590
+#, python-format
+msgid "LDAP delete: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:595
+#, python-format
+msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:146
+#, python-format
+msgid "FakeLdap initialize url=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:156
+#, python-format
+msgid "FakeLdap bind dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:163
+#, python-format
+msgid "FakeLdap bind fail: dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:170
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:175
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s does not match"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:190
+#, python-format
+msgid "FakeLdap add item: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:193
+#, python-format
+msgid "FakeLdap add item failed: dn=%s is already in store."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:207 keystone/common/ldap/fakeldap.py:221
+#, python-format
+msgid "FakeLdap delete item: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:211 keystone/common/ldap/fakeldap.py:225
+#, python-format
+msgid "FakeLdap delete item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:240
+#, python-format
+msgid "FakeLdap modify item: dn=%(dn)s attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:245
+#, python-format
+msgid "FakeLdap modify item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:262
+#, python-format
+msgid "FakeLdap modify item failed: item has no attribute \"%s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:273
+#, python-format
+msgid ""
+"FakeLdap modify item failed: item has no attribute \"%(k)s\" with value "
+"\"%(v)s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:279
+#, python-format
+msgid "FakeLdap modify item failed: unknown command %s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:281
+#, python-format
+msgid "modify_s action %s not implemented"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:300
+#, python-format
+msgid "FakeLdap search at dn=%(dn)s scope=%(scope)s query=%(query)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:306
+msgid "FakeLdap search fail: dn not found for SCOPE_BASE"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:320
+#, python-format
+msgid "Search scope %s not implemented."
+msgstr ""
+
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
+#, python-format
+msgid "Got mysql server has gone away: %s"
+msgstr ""
+
+#: keystone/common/sql/legacy.py:188
+#, python-format
+msgid "Cannot migrate EC2 credential: %s"
+msgstr ""
+
+#: keystone/common/sql/migration.py:47
+msgid "version should be an integer"
+msgstr ""
+
+#: keystone/common/sql/nova.py:65
+#, python-format
+msgid "Create tenant %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:82
+#, python-format
+msgid "Create user %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:91
+#, python-format
+msgid "Add user %(user_id)s to tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:100
+#, python-format
+msgid "Ignoring existing role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:107
+#, python-format
+msgid "Create role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:117
+#, python-format
+msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:136
+#, python-format
+msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/identity/controllers.py:952
+#, python-format
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
+msgstr ""
+
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
+msgid "User not found in group"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:189
+#, python-format
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:334
+msgid "Changing Name not supported by LDAP"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:347
+#, python-format
+msgid "User %(user_id)s is already a member of group %(group_id)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:394
+#, python-format
+msgid "Failed to understand rule %(rule)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:404
+#, python-format
+msgid "No handler for matches of kind %s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:679
+#, python-format
+msgid "Failed to understand rule %(rule)r"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
+#: keystone/policy/backends/rules.py:93
+#, python-format
+msgid "enforce %(action)s: %(credentials)s"
+msgstr ""
+
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
+msgid "Token does not belong to specified tenant."
+msgstr ""
+
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
+msgstr ""
+
+#: keystone/token/backends/memcache.py:144
+#, python-format
+msgid ""
+"Successful set of token-index-list for user-key \"%(user_key)s\", "
+"#%(count)d records"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:154
+#, python-format
+msgid ""
+"Failed to set token-index-list for user-key \"%(user_key)s\". Attempt "
+"%(cas_retry)d of %(cas_retry_max)d"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:163
+msgid "Unable to add token user list"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:172
+msgid "Unable to add token to revocation list."
+msgstr ""
+
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
+#~ msgid "User have no access to project"
+#~ msgstr ""
+
+#~ msgid "User have no access to domain"
+#~ msgstr ""
+
+#~ msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+#~ msgstr ""
+
diff --git a/keystone/locale/sw_KE/LC_MESSAGES/keystone.po b/keystone/locale/sw_KE/LC_MESSAGES/keystone.po
new file mode 100644
index 00000000..f3a77803
--- /dev/null
+++ b/keystone/locale/sw_KE/LC_MESSAGES/keystone.po
@@ -0,0 +1,847 @@
+# Swahili (Kenya) translations for keystone.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the keystone project.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: Keystone\n"
+"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
+"PO-Revision-Date: 2013-07-29 22:01+0000\n"
+"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
+"Language-Team: Swahili (Kenya) "
+"(http://www.transifex.com/projects/p/openstack/language/sw_KE/)\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: keystone/clean.py:23
+#, python-format
+msgid "%s cannot be empty."
+msgstr ""
+
+#: keystone/clean.py:25
+#, python-format
+msgid "%(property_name)s cannot be less than %(min_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:29
+#, python-format
+msgid "%(property_name)s should not be greater than %(max_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:36
+#, python-format
+msgid "%(property_name)s is not a %(display_expected_type)s"
+msgstr ""
+
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
+#: keystone/test.py:117
+#, python-format
+msgid "Failed to checkout %s"
+msgstr ""
+
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr ""
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr ""
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
+#, python-format
+msgid "Project is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
+#, python-format
+msgid "Domain is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
+#, python-format
+msgid "User is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:262
+msgid "Scoping to both domain and project is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:265
+msgid "Scoping to both domain and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:268
+msgid "Scoping to both project and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:353
+msgid "User not found"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
+#, python-format
+msgid "Unable to lookup user %s"
+msgstr ""
+
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
+msgstr ""
+
+#: keystone/catalog/core.py:38
+#, python-format
+msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s"
+msgstr ""
+
+#: keystone/catalog/core.py:43
+#, python-format
+msgid ""
+"Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing "
+"brackets ?)"
+msgstr ""
+
+#: keystone/catalog/core.py:49
+#, python-format
+msgid ""
+"Malformed endpoint %s - incomplete format (are you "
+"missing a type notifier ?)"
+msgstr ""
+
+#: keystone/catalog/backends/templated.py:109
+#, python-format
+msgid "Unable to open template file %s"
+msgstr ""
+
+#: keystone/common/cms.py:26
+#, python-format
+msgid "Verify error: %s"
+msgstr ""
+
+#: keystone/common/cms.py:118
+msgid ""
+"Signing error: Unable to load certificate - ensure you've configured PKI "
+"with 'keystone-manage pki_setup'"
+msgstr ""
+
+#: keystone/common/cms.py:122
+#, python-format
+msgid "Signing error: %s"
+msgstr ""
+
+#: keystone/common/config.py:89
+#, python-format
+msgid "Unable to locate specified logging config file: %s"
+msgstr ""
+
+#: keystone/common/config.py:107
+msgid "Invalid syslog facility"
+msgstr ""
+
+#: keystone/common/controller.py:18
+#, python-format
+msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
+msgstr ""
+
+#: keystone/common/controller.py:25
+msgid "RBAC: Invalid token"
+msgstr ""
+
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
+msgid "RBAC: Invalid user"
+msgstr ""
+
+#: keystone/common/controller.py:45
+msgid "RBAC: Proceeding without project"
+msgstr ""
+
+#: keystone/common/controller.py:65
+msgid "RBAC: Proceeding without tenant"
+msgstr ""
+
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
+msgid "RBAC: Bypassing authorization"
+msgstr ""
+
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
+msgid "RBAC: Authorization granted"
+msgstr ""
+
+#: keystone/common/controller.py:134
+#, python-format
+msgid "RBAC: Adding query filter params (%s)"
+msgstr ""
+
+#: keystone/common/controller.py:322
+msgid "Invalid token in normalize_domain_id"
+msgstr ""
+
+#: keystone/common/utils.py:233
+msgid ""
+"Error setting up the debug environment. Verify that the option --debug-"
+"url has the format <host>:<port> and that a debugger processes is "
+"listening on that port."
+msgstr ""
+
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
+#, python-format
+msgid "arg_dict: %s"
+msgstr ""
+
+#: keystone/common/wsgi.py:243
+#, python-format
+msgid "Authorization failed. %(exception)s from %(remote_addr)s"
+msgstr ""
+
+#: keystone/common/wsgi.py:487
+msgid "The resource could not be found."
+msgstr ""
+
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
+#, python-format
+msgid "Starting %(arg0)s on %(host)s:%(port)s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:113
+msgid "Server error"
+msgstr ""
+
+#: keystone/common/ldap/core.py:79
+#, python-format
+msgid "Invalid LDAP deref option: %s. Choose one of: "
+msgstr ""
+
+#: keystone/common/ldap/core.py:87
+#, python-format
+msgid "Invalid LDAP TLS certs option: %(option). Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:99
+#, python-format
+msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:189
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%s\". Format must be "
+"<ldap_attribute>:<keystone_attribute>"
+msgstr ""
+
+#: keystone/common/ldap/core.py:195
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%(item)s\". Value "
+"\"%(attr_map)s\" must use one of %(keys)s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
+#, python-format
+msgid "Duplicate name, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
+#, python-format
+msgid "Duplicate ID, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:294
+#, python-format
+msgid "LDAP %s create"
+msgstr ""
+
+#: keystone/common/ldap/core.py:372
+#, python-format
+msgid "LDAP %s update"
+msgstr ""
+
+#: keystone/common/ldap/core.py:405
+#, python-format
+msgid "LDAP %s delete"
+msgstr ""
+
+#: keystone/common/ldap/core.py:430
+#, python-format
+msgid "LDAP init: url=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:431
+#, python-format
+msgid ""
+"LDAP init: use_tls=%(use_tls)s\n"
+"tls_cacertfile=%(tls_cacertfile)s\n"
+"tls_cacertdir=%(tls_cacertdir)s\n"
+"tls_req_cert=%(tls_req_cert)s\n"
+"tls_avail=%(tls_avail)s\n"
+msgstr ""
+
+#: keystone/common/ldap/core.py:450
+msgid "Invalid TLS / LDAPS combination"
+msgstr ""
+
+#: keystone/common/ldap/core.py:454
+#, python-format
+msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available"
+msgstr ""
+
+#: keystone/common/ldap/core.py:464
+#, python-format
+msgid "tls_cacertfile %s not found or is not a file"
+msgstr ""
+
+#: keystone/common/ldap/core.py:476
+#, python-format
+msgid "tls_cacertdir %s not found or is not a directory"
+msgstr ""
+
+#: keystone/common/ldap/core.py:483
+#, python-format
+msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:497
+#, python-format
+msgid "LDAP bind: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:508
+#, python-format
+msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:514
+#, python-format
+msgid ""
+"LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, "
+"attrs=%(attrlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:567
+msgid ""
+"LDAP Server does not support paging. Disable paging in keystone.conf to "
+"avoid this message."
+msgstr ""
+
+#: keystone/common/ldap/core.py:584
+#, python-format
+msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:590
+#, python-format
+msgid "LDAP delete: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:595
+#, python-format
+msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:146
+#, python-format
+msgid "FakeLdap initialize url=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:156
+#, python-format
+msgid "FakeLdap bind dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:163
+#, python-format
+msgid "FakeLdap bind fail: dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:170
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:175
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s does not match"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:190
+#, python-format
+msgid "FakeLdap add item: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:193
+#, python-format
+msgid "FakeLdap add item failed: dn=%s is already in store."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:207 keystone/common/ldap/fakeldap.py:221
+#, python-format
+msgid "FakeLdap delete item: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:211 keystone/common/ldap/fakeldap.py:225
+#, python-format
+msgid "FakeLdap delete item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:240
+#, python-format
+msgid "FakeLdap modify item: dn=%(dn)s attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:245
+#, python-format
+msgid "FakeLdap modify item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:262
+#, python-format
+msgid "FakeLdap modify item failed: item has no attribute \"%s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:273
+#, python-format
+msgid ""
+"FakeLdap modify item failed: item has no attribute \"%(k)s\" with value "
+"\"%(v)s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:279
+#, python-format
+msgid "FakeLdap modify item failed: unknown command %s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:281
+#, python-format
+msgid "modify_s action %s not implemented"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:300
+#, python-format
+msgid "FakeLdap search at dn=%(dn)s scope=%(scope)s query=%(query)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:306
+msgid "FakeLdap search fail: dn not found for SCOPE_BASE"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:320
+#, python-format
+msgid "Search scope %s not implemented."
+msgstr ""
+
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
+#, python-format
+msgid "Got mysql server has gone away: %s"
+msgstr ""
+
+#: keystone/common/sql/legacy.py:188
+#, python-format
+msgid "Cannot migrate EC2 credential: %s"
+msgstr ""
+
+#: keystone/common/sql/migration.py:47
+msgid "version should be an integer"
+msgstr ""
+
+#: keystone/common/sql/nova.py:65
+#, python-format
+msgid "Create tenant %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:82
+#, python-format
+msgid "Create user %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:91
+#, python-format
+msgid "Add user %(user_id)s to tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:100
+#, python-format
+msgid "Ignoring existing role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:107
+#, python-format
+msgid "Create role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:117
+#, python-format
+msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:136
+#, python-format
+msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/identity/controllers.py:952
+#, python-format
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
+msgstr ""
+
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
+msgid "User not found in group"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:189
+#, python-format
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:334
+msgid "Changing Name not supported by LDAP"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:347
+#, python-format
+msgid "User %(user_id)s is already a member of group %(group_id)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:394
+#, python-format
+msgid "Failed to understand rule %(rule)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:404
+#, python-format
+msgid "No handler for matches of kind %s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:679
+#, python-format
+msgid "Failed to understand rule %(rule)r"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
+#: keystone/policy/backends/rules.py:93
+#, python-format
+msgid "enforce %(action)s: %(credentials)s"
+msgstr ""
+
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
+msgid "Token does not belong to specified tenant."
+msgstr ""
+
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
+msgstr ""
+
+#: keystone/token/backends/memcache.py:144
+#, python-format
+msgid ""
+"Successful set of token-index-list for user-key \"%(user_key)s\", "
+"#%(count)d records"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:154
+#, python-format
+msgid ""
+"Failed to set token-index-list for user-key \"%(user_key)s\". Attempt "
+"%(cas_retry)d of %(cas_retry_max)d"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:163
+msgid "Unable to add token user list"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:172
+msgid "Unable to add token to revocation list."
+msgstr ""
+
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
diff --git a/keystone/locale/tl/LC_MESSAGES/keystone.po b/keystone/locale/tl/LC_MESSAGES/keystone.po
new file mode 100644
index 00000000..b1186d54
--- /dev/null
+++ b/keystone/locale/tl/LC_MESSAGES/keystone.po
@@ -0,0 +1,847 @@
+# Filipino (Philippines) translations for keystone.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the keystone project.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: Keystone\n"
+"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
+"PO-Revision-Date: 2013-07-29 22:01+0000\n"
+"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
+"Language-Team: Tagalog "
+"(http://www.transifex.com/projects/p/openstack/language/tl/)\n"
+"Plural-Forms: nplurals=2; plural=(n > 1)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: keystone/clean.py:23
+#, python-format
+msgid "%s cannot be empty."
+msgstr ""
+
+#: keystone/clean.py:25
+#, python-format
+msgid "%(property_name)s cannot be less than %(min_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:29
+#, python-format
+msgid "%(property_name)s should not be greater than %(max_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:36
+#, python-format
+msgid "%(property_name)s is not a %(display_expected_type)s"
+msgstr ""
+
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
+#: keystone/test.py:117
+#, python-format
+msgid "Failed to checkout %s"
+msgstr ""
+
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr ""
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr ""
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
+#, python-format
+msgid "Project is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
+#, python-format
+msgid "Domain is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
+#, python-format
+msgid "User is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:262
+msgid "Scoping to both domain and project is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:265
+msgid "Scoping to both domain and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:268
+msgid "Scoping to both project and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:353
+msgid "User not found"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
+#, python-format
+msgid "Unable to lookup user %s"
+msgstr ""
+
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
+msgstr ""
+
+#: keystone/catalog/core.py:38
+#, python-format
+msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s"
+msgstr ""
+
+#: keystone/catalog/core.py:43
+#, python-format
+msgid ""
+"Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing "
+"brackets ?)"
+msgstr ""
+
+#: keystone/catalog/core.py:49
+#, python-format
+msgid ""
+"Malformed endpoint %s - incomplete format (are you "
+"missing a type notifier ?)"
+msgstr ""
+
+#: keystone/catalog/backends/templated.py:109
+#, python-format
+msgid "Unable to open template file %s"
+msgstr ""
+
+#: keystone/common/cms.py:26
+#, python-format
+msgid "Verify error: %s"
+msgstr ""
+
+#: keystone/common/cms.py:118
+msgid ""
+"Signing error: Unable to load certificate - ensure you've configured PKI "
+"with 'keystone-manage pki_setup'"
+msgstr ""
+
+#: keystone/common/cms.py:122
+#, python-format
+msgid "Signing error: %s"
+msgstr ""
+
+#: keystone/common/config.py:89
+#, python-format
+msgid "Unable to locate specified logging config file: %s"
+msgstr ""
+
+#: keystone/common/config.py:107
+msgid "Invalid syslog facility"
+msgstr ""
+
+#: keystone/common/controller.py:18
+#, python-format
+msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
+msgstr ""
+
+#: keystone/common/controller.py:25
+msgid "RBAC: Invalid token"
+msgstr ""
+
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
+msgid "RBAC: Invalid user"
+msgstr ""
+
+#: keystone/common/controller.py:45
+msgid "RBAC: Proceeding without project"
+msgstr ""
+
+#: keystone/common/controller.py:65
+msgid "RBAC: Proceeding without tenant"
+msgstr ""
+
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
+msgid "RBAC: Bypassing authorization"
+msgstr ""
+
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
+msgid "RBAC: Authorization granted"
+msgstr ""
+
+#: keystone/common/controller.py:134
+#, python-format
+msgid "RBAC: Adding query filter params (%s)"
+msgstr ""
+
+#: keystone/common/controller.py:322
+msgid "Invalid token in normalize_domain_id"
+msgstr ""
+
+#: keystone/common/utils.py:233
+msgid ""
+"Error setting up the debug environment. Verify that the option --debug-"
+"url has the format <host>:<port> and that a debugger processes is "
+"listening on that port."
+msgstr ""
+
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
+#, python-format
+msgid "arg_dict: %s"
+msgstr ""
+
+#: keystone/common/wsgi.py:243
+#, python-format
+msgid "Authorization failed. %(exception)s from %(remote_addr)s"
+msgstr ""
+
+#: keystone/common/wsgi.py:487
+msgid "The resource could not be found."
+msgstr ""
+
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
+#, python-format
+msgid "Starting %(arg0)s on %(host)s:%(port)s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:113
+msgid "Server error"
+msgstr ""
+
+#: keystone/common/ldap/core.py:79
+#, python-format
+msgid "Invalid LDAP deref option: %s. Choose one of: "
+msgstr ""
+
+#: keystone/common/ldap/core.py:87
+#, python-format
+msgid "Invalid LDAP TLS certs option: %(option). Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:99
+#, python-format
+msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:189
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%s\". Format must be "
+"<ldap_attribute>:<keystone_attribute>"
+msgstr ""
+
+#: keystone/common/ldap/core.py:195
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%(item)s\". Value "
+"\"%(attr_map)s\" must use one of %(keys)s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
+#, python-format
+msgid "Duplicate name, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
+#, python-format
+msgid "Duplicate ID, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:294
+#, python-format
+msgid "LDAP %s create"
+msgstr ""
+
+#: keystone/common/ldap/core.py:372
+#, python-format
+msgid "LDAP %s update"
+msgstr ""
+
+#: keystone/common/ldap/core.py:405
+#, python-format
+msgid "LDAP %s delete"
+msgstr ""
+
+#: keystone/common/ldap/core.py:430
+#, python-format
+msgid "LDAP init: url=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:431
+#, python-format
+msgid ""
+"LDAP init: use_tls=%(use_tls)s\n"
+"tls_cacertfile=%(tls_cacertfile)s\n"
+"tls_cacertdir=%(tls_cacertdir)s\n"
+"tls_req_cert=%(tls_req_cert)s\n"
+"tls_avail=%(tls_avail)s\n"
+msgstr ""
+
+#: keystone/common/ldap/core.py:450
+msgid "Invalid TLS / LDAPS combination"
+msgstr ""
+
+#: keystone/common/ldap/core.py:454
+#, python-format
+msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available"
+msgstr ""
+
+#: keystone/common/ldap/core.py:464
+#, python-format
+msgid "tls_cacertfile %s not found or is not a file"
+msgstr ""
+
+#: keystone/common/ldap/core.py:476
+#, python-format
+msgid "tls_cacertdir %s not found or is not a directory"
+msgstr ""
+
+#: keystone/common/ldap/core.py:483
+#, python-format
+msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:497
+#, python-format
+msgid "LDAP bind: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:508
+#, python-format
+msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:514
+#, python-format
+msgid ""
+"LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, "
+"attrs=%(attrlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:567
+msgid ""
+"LDAP Server does not support paging. Disable paging in keystone.conf to "
+"avoid this message."
+msgstr ""
+
+#: keystone/common/ldap/core.py:584
+#, python-format
+msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:590
+#, python-format
+msgid "LDAP delete: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:595
+#, python-format
+msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:146
+#, python-format
+msgid "FakeLdap initialize url=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:156
+#, python-format
+msgid "FakeLdap bind dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:163
+#, python-format
+msgid "FakeLdap bind fail: dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:170
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:175
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s does not match"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:190
+#, python-format
+msgid "FakeLdap add item: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:193
+#, python-format
+msgid "FakeLdap add item failed: dn=%s is already in store."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:207 keystone/common/ldap/fakeldap.py:221
+#, python-format
+msgid "FakeLdap delete item: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:211 keystone/common/ldap/fakeldap.py:225
+#, python-format
+msgid "FakeLdap delete item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:240
+#, python-format
+msgid "FakeLdap modify item: dn=%(dn)s attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:245
+#, python-format
+msgid "FakeLdap modify item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:262
+#, python-format
+msgid "FakeLdap modify item failed: item has no attribute \"%s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:273
+#, python-format
+msgid ""
+"FakeLdap modify item failed: item has no attribute \"%(k)s\" with value "
+"\"%(v)s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:279
+#, python-format
+msgid "FakeLdap modify item failed: unknown command %s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:281
+#, python-format
+msgid "modify_s action %s not implemented"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:300
+#, python-format
+msgid "FakeLdap search at dn=%(dn)s scope=%(scope)s query=%(query)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:306
+msgid "FakeLdap search fail: dn not found for SCOPE_BASE"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:320
+#, python-format
+msgid "Search scope %s not implemented."
+msgstr ""
+
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
+#, python-format
+msgid "Got mysql server has gone away: %s"
+msgstr ""
+
+#: keystone/common/sql/legacy.py:188
+#, python-format
+msgid "Cannot migrate EC2 credential: %s"
+msgstr ""
+
+#: keystone/common/sql/migration.py:47
+msgid "version should be an integer"
+msgstr ""
+
+#: keystone/common/sql/nova.py:65
+#, python-format
+msgid "Create tenant %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:82
+#, python-format
+msgid "Create user %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:91
+#, python-format
+msgid "Add user %(user_id)s to tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:100
+#, python-format
+msgid "Ignoring existing role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:107
+#, python-format
+msgid "Create role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:117
+#, python-format
+msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:136
+#, python-format
+msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/identity/controllers.py:952
+#, python-format
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
+msgstr ""
+
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
+msgid "User not found in group"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:189
+#, python-format
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:334
+msgid "Changing Name not supported by LDAP"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:347
+#, python-format
+msgid "User %(user_id)s is already a member of group %(group_id)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:394
+#, python-format
+msgid "Failed to understand rule %(rule)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:404
+#, python-format
+msgid "No handler for matches of kind %s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:679
+#, python-format
+msgid "Failed to understand rule %(rule)r"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
+#: keystone/policy/backends/rules.py:93
+#, python-format
+msgid "enforce %(action)s: %(credentials)s"
+msgstr ""
+
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
+msgid "Token does not belong to specified tenant."
+msgstr ""
+
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
+msgstr ""
+
+#: keystone/token/backends/memcache.py:144
+#, python-format
+msgid ""
+"Successful set of token-index-list for user-key \"%(user_key)s\", "
+"#%(count)d records"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:154
+#, python-format
+msgid ""
+"Failed to set token-index-list for user-key \"%(user_key)s\". Attempt "
+"%(cas_retry)d of %(cas_retry_max)d"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:163
+msgid "Unable to add token user list"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:172
+msgid "Unable to add token to revocation list."
+msgstr ""
+
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
diff --git a/keystone/locale/tr_TR/LC_MESSAGES/keystone.po b/keystone/locale/tr_TR/LC_MESSAGES/keystone.po
new file mode 100644
index 00000000..866c94eb
--- /dev/null
+++ b/keystone/locale/tr_TR/LC_MESSAGES/keystone.po
@@ -0,0 +1,847 @@
+# Turkish (Turkey) translations for keystone.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the keystone project.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: Keystone\n"
+"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
+"PO-Revision-Date: 2013-07-29 22:01+0000\n"
+"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
+"Language-Team: Turkish (Turkey) "
+"(http://www.transifex.com/projects/p/openstack/language/tr_TR/)\n"
+"Plural-Forms: nplurals=1; plural=0\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: keystone/clean.py:23
+#, python-format
+msgid "%s cannot be empty."
+msgstr ""
+
+#: keystone/clean.py:25
+#, python-format
+msgid "%(property_name)s cannot be less than %(min_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:29
+#, python-format
+msgid "%(property_name)s should not be greater than %(max_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:36
+#, python-format
+msgid "%(property_name)s is not a %(display_expected_type)s"
+msgstr ""
+
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
+#: keystone/test.py:117
+#, python-format
+msgid "Failed to checkout %s"
+msgstr ""
+
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr ""
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr ""
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
+#, python-format
+msgid "Project is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
+#, python-format
+msgid "Domain is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
+#, python-format
+msgid "User is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:262
+msgid "Scoping to both domain and project is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:265
+msgid "Scoping to both domain and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:268
+msgid "Scoping to both project and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:353
+msgid "User not found"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
+#, python-format
+msgid "Unable to lookup user %s"
+msgstr ""
+
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
+msgstr ""
+
+#: keystone/catalog/core.py:38
+#, python-format
+msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s"
+msgstr ""
+
+#: keystone/catalog/core.py:43
+#, python-format
+msgid ""
+"Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing "
+"brackets ?)"
+msgstr ""
+
+#: keystone/catalog/core.py:49
+#, python-format
+msgid ""
+"Malformed endpoint %s - incomplete format (are you "
+"missing a type notifier ?)"
+msgstr ""
+
+#: keystone/catalog/backends/templated.py:109
+#, python-format
+msgid "Unable to open template file %s"
+msgstr ""
+
+#: keystone/common/cms.py:26
+#, python-format
+msgid "Verify error: %s"
+msgstr ""
+
+#: keystone/common/cms.py:118
+msgid ""
+"Signing error: Unable to load certificate - ensure you've configured PKI "
+"with 'keystone-manage pki_setup'"
+msgstr ""
+
+#: keystone/common/cms.py:122
+#, python-format
+msgid "Signing error: %s"
+msgstr ""
+
+#: keystone/common/config.py:89
+#, python-format
+msgid "Unable to locate specified logging config file: %s"
+msgstr ""
+
+#: keystone/common/config.py:107
+msgid "Invalid syslog facility"
+msgstr ""
+
+#: keystone/common/controller.py:18
+#, python-format
+msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
+msgstr ""
+
+#: keystone/common/controller.py:25
+msgid "RBAC: Invalid token"
+msgstr ""
+
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
+msgid "RBAC: Invalid user"
+msgstr ""
+
+#: keystone/common/controller.py:45
+msgid "RBAC: Proceeding without project"
+msgstr ""
+
+#: keystone/common/controller.py:65
+msgid "RBAC: Proceeding without tenant"
+msgstr ""
+
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
+msgid "RBAC: Bypassing authorization"
+msgstr ""
+
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
+msgid "RBAC: Authorization granted"
+msgstr ""
+
+#: keystone/common/controller.py:134
+#, python-format
+msgid "RBAC: Adding query filter params (%s)"
+msgstr ""
+
+#: keystone/common/controller.py:322
+msgid "Invalid token in normalize_domain_id"
+msgstr ""
+
+#: keystone/common/utils.py:233
+msgid ""
+"Error setting up the debug environment. Verify that the option --debug-"
+"url has the format <host>:<port> and that a debugger processes is "
+"listening on that port."
+msgstr ""
+
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
+#, python-format
+msgid "arg_dict: %s"
+msgstr ""
+
+#: keystone/common/wsgi.py:243
+#, python-format
+msgid "Authorization failed. %(exception)s from %(remote_addr)s"
+msgstr ""
+
+#: keystone/common/wsgi.py:487
+msgid "The resource could not be found."
+msgstr ""
+
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
+#, python-format
+msgid "Starting %(arg0)s on %(host)s:%(port)s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:113
+msgid "Server error"
+msgstr ""
+
+#: keystone/common/ldap/core.py:79
+#, python-format
+msgid "Invalid LDAP deref option: %s. Choose one of: "
+msgstr ""
+
+#: keystone/common/ldap/core.py:87
+#, python-format
+msgid "Invalid LDAP TLS certs option: %(option). Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:99
+#, python-format
+msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:189
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%s\". Format must be "
+"<ldap_attribute>:<keystone_attribute>"
+msgstr ""
+
+#: keystone/common/ldap/core.py:195
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%(item)s\". Value "
+"\"%(attr_map)s\" must use one of %(keys)s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
+#, python-format
+msgid "Duplicate name, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
+#, python-format
+msgid "Duplicate ID, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:294
+#, python-format
+msgid "LDAP %s create"
+msgstr ""
+
+#: keystone/common/ldap/core.py:372
+#, python-format
+msgid "LDAP %s update"
+msgstr ""
+
+#: keystone/common/ldap/core.py:405
+#, python-format
+msgid "LDAP %s delete"
+msgstr ""
+
+#: keystone/common/ldap/core.py:430
+#, python-format
+msgid "LDAP init: url=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:431
+#, python-format
+msgid ""
+"LDAP init: use_tls=%(use_tls)s\n"
+"tls_cacertfile=%(tls_cacertfile)s\n"
+"tls_cacertdir=%(tls_cacertdir)s\n"
+"tls_req_cert=%(tls_req_cert)s\n"
+"tls_avail=%(tls_avail)s\n"
+msgstr ""
+
+#: keystone/common/ldap/core.py:450
+msgid "Invalid TLS / LDAPS combination"
+msgstr ""
+
+#: keystone/common/ldap/core.py:454
+#, python-format
+msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available"
+msgstr ""
+
+#: keystone/common/ldap/core.py:464
+#, python-format
+msgid "tls_cacertfile %s not found or is not a file"
+msgstr ""
+
+#: keystone/common/ldap/core.py:476
+#, python-format
+msgid "tls_cacertdir %s not found or is not a directory"
+msgstr ""
+
+#: keystone/common/ldap/core.py:483
+#, python-format
+msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:497
+#, python-format
+msgid "LDAP bind: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:508
+#, python-format
+msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:514
+#, python-format
+msgid ""
+"LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, "
+"attrs=%(attrlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:567
+msgid ""
+"LDAP Server does not support paging. Disable paging in keystone.conf to "
+"avoid this message."
+msgstr ""
+
+#: keystone/common/ldap/core.py:584
+#, python-format
+msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:590
+#, python-format
+msgid "LDAP delete: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:595
+#, python-format
+msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:146
+#, python-format
+msgid "FakeLdap initialize url=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:156
+#, python-format
+msgid "FakeLdap bind dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:163
+#, python-format
+msgid "FakeLdap bind fail: dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:170
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:175
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s does not match"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:190
+#, python-format
+msgid "FakeLdap add item: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:193
+#, python-format
+msgid "FakeLdap add item failed: dn=%s is already in store."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:207 keystone/common/ldap/fakeldap.py:221
+#, python-format
+msgid "FakeLdap delete item: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:211 keystone/common/ldap/fakeldap.py:225
+#, python-format
+msgid "FakeLdap delete item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:240
+#, python-format
+msgid "FakeLdap modify item: dn=%(dn)s attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:245
+#, python-format
+msgid "FakeLdap modify item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:262
+#, python-format
+msgid "FakeLdap modify item failed: item has no attribute \"%s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:273
+#, python-format
+msgid ""
+"FakeLdap modify item failed: item has no attribute \"%(k)s\" with value "
+"\"%(v)s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:279
+#, python-format
+msgid "FakeLdap modify item failed: unknown command %s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:281
+#, python-format
+msgid "modify_s action %s not implemented"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:300
+#, python-format
+msgid "FakeLdap search at dn=%(dn)s scope=%(scope)s query=%(query)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:306
+msgid "FakeLdap search fail: dn not found for SCOPE_BASE"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:320
+#, python-format
+msgid "Search scope %s not implemented."
+msgstr ""
+
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
+#, python-format
+msgid "Got mysql server has gone away: %s"
+msgstr ""
+
+#: keystone/common/sql/legacy.py:188
+#, python-format
+msgid "Cannot migrate EC2 credential: %s"
+msgstr ""
+
+#: keystone/common/sql/migration.py:47
+msgid "version should be an integer"
+msgstr ""
+
+#: keystone/common/sql/nova.py:65
+#, python-format
+msgid "Create tenant %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:82
+#, python-format
+msgid "Create user %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:91
+#, python-format
+msgid "Add user %(user_id)s to tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:100
+#, python-format
+msgid "Ignoring existing role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:107
+#, python-format
+msgid "Create role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:117
+#, python-format
+msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:136
+#, python-format
+msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/identity/controllers.py:952
+#, python-format
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
+msgstr ""
+
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
+msgid "User not found in group"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:189
+#, python-format
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:334
+msgid "Changing Name not supported by LDAP"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:347
+#, python-format
+msgid "User %(user_id)s is already a member of group %(group_id)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:394
+#, python-format
+msgid "Failed to understand rule %(rule)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:404
+#, python-format
+msgid "No handler for matches of kind %s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:679
+#, python-format
+msgid "Failed to understand rule %(rule)r"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
+#: keystone/policy/backends/rules.py:93
+#, python-format
+msgid "enforce %(action)s: %(credentials)s"
+msgstr ""
+
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
+msgid "Token does not belong to specified tenant."
+msgstr ""
+
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
+msgstr ""
+
+#: keystone/token/backends/memcache.py:144
+#, python-format
+msgid ""
+"Successful set of token-index-list for user-key \"%(user_key)s\", "
+"#%(count)d records"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:154
+#, python-format
+msgid ""
+"Failed to set token-index-list for user-key \"%(user_key)s\". Attempt "
+"%(cas_retry)d of %(cas_retry_max)d"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:163
+msgid "Unable to add token user list"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:172
+msgid "Unable to add token to revocation list."
+msgstr ""
+
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
diff --git a/keystone/locale/uk/LC_MESSAGES/keystone.po b/keystone/locale/uk/LC_MESSAGES/keystone.po
new file mode 100644
index 00000000..4d8e5cef
--- /dev/null
+++ b/keystone/locale/uk/LC_MESSAGES/keystone.po
@@ -0,0 +1,848 @@
+# Ukrainian translations for keystone.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the keystone project.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: Keystone\n"
+"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
+"PO-Revision-Date: 2013-07-29 22:01+0000\n"
+"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
+"Language-Team: Ukrainian "
+"(http://www.transifex.com/projects/p/openstack/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 1.3\n"
+
+#: keystone/clean.py:23
+#, python-format
+msgid "%s cannot be empty."
+msgstr ""
+
+#: keystone/clean.py:25
+#, python-format
+msgid "%(property_name)s cannot be less than %(min_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:29
+#, python-format
+msgid "%(property_name)s should not be greater than %(max_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:36
+#, python-format
+msgid "%(property_name)s is not a %(display_expected_type)s"
+msgstr ""
+
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
+#: keystone/test.py:117
+#, python-format
+msgid "Failed to checkout %s"
+msgstr ""
+
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr ""
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr ""
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
+#, python-format
+msgid "Project is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
+#, python-format
+msgid "Domain is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
+#, python-format
+msgid "User is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:262
+msgid "Scoping to both domain and project is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:265
+msgid "Scoping to both domain and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:268
+msgid "Scoping to both project and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:353
+msgid "User not found"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
+#, python-format
+msgid "Unable to lookup user %s"
+msgstr ""
+
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
+msgstr ""
+
+#: keystone/catalog/core.py:38
+#, python-format
+msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s"
+msgstr ""
+
+#: keystone/catalog/core.py:43
+#, python-format
+msgid ""
+"Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing "
+"brackets ?)"
+msgstr ""
+
+#: keystone/catalog/core.py:49
+#, python-format
+msgid ""
+"Malformed endpoint %s - incomplete format (are you "
+"missing a type notifier ?)"
+msgstr ""
+
+#: keystone/catalog/backends/templated.py:109
+#, python-format
+msgid "Unable to open template file %s"
+msgstr ""
+
+#: keystone/common/cms.py:26
+#, python-format
+msgid "Verify error: %s"
+msgstr ""
+
+#: keystone/common/cms.py:118
+msgid ""
+"Signing error: Unable to load certificate - ensure you've configured PKI "
+"with 'keystone-manage pki_setup'"
+msgstr ""
+
+#: keystone/common/cms.py:122
+#, python-format
+msgid "Signing error: %s"
+msgstr ""
+
+#: keystone/common/config.py:89
+#, python-format
+msgid "Unable to locate specified logging config file: %s"
+msgstr ""
+
+#: keystone/common/config.py:107
+msgid "Invalid syslog facility"
+msgstr ""
+
+#: keystone/common/controller.py:18
+#, python-format
+msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
+msgstr ""
+
+#: keystone/common/controller.py:25
+msgid "RBAC: Invalid token"
+msgstr ""
+
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
+msgid "RBAC: Invalid user"
+msgstr ""
+
+#: keystone/common/controller.py:45
+msgid "RBAC: Proceeding without project"
+msgstr ""
+
+#: keystone/common/controller.py:65
+msgid "RBAC: Proceeding without tenant"
+msgstr ""
+
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
+msgid "RBAC: Bypassing authorization"
+msgstr ""
+
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
+msgid "RBAC: Authorization granted"
+msgstr ""
+
+#: keystone/common/controller.py:134
+#, python-format
+msgid "RBAC: Adding query filter params (%s)"
+msgstr ""
+
+#: keystone/common/controller.py:322
+msgid "Invalid token in normalize_domain_id"
+msgstr ""
+
+#: keystone/common/utils.py:233
+msgid ""
+"Error setting up the debug environment. Verify that the option --debug-"
+"url has the format <host>:<port> and that a debugger processes is "
+"listening on that port."
+msgstr ""
+
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
+#, python-format
+msgid "arg_dict: %s"
+msgstr ""
+
+#: keystone/common/wsgi.py:243
+#, python-format
+msgid "Authorization failed. %(exception)s from %(remote_addr)s"
+msgstr ""
+
+#: keystone/common/wsgi.py:487
+msgid "The resource could not be found."
+msgstr ""
+
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
+#, python-format
+msgid "Starting %(arg0)s on %(host)s:%(port)s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:113
+msgid "Server error"
+msgstr ""
+
+#: keystone/common/ldap/core.py:79
+#, python-format
+msgid "Invalid LDAP deref option: %s. Choose one of: "
+msgstr ""
+
+#: keystone/common/ldap/core.py:87
+#, python-format
+msgid "Invalid LDAP TLS certs option: %(option). Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:99
+#, python-format
+msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:189
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%s\". Format must be "
+"<ldap_attribute>:<keystone_attribute>"
+msgstr ""
+
+#: keystone/common/ldap/core.py:195
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%(item)s\". Value "
+"\"%(attr_map)s\" must use one of %(keys)s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
+#, python-format
+msgid "Duplicate name, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
+#, python-format
+msgid "Duplicate ID, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:294
+#, python-format
+msgid "LDAP %s create"
+msgstr ""
+
+#: keystone/common/ldap/core.py:372
+#, python-format
+msgid "LDAP %s update"
+msgstr ""
+
+#: keystone/common/ldap/core.py:405
+#, python-format
+msgid "LDAP %s delete"
+msgstr ""
+
+#: keystone/common/ldap/core.py:430
+#, python-format
+msgid "LDAP init: url=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:431
+#, python-format
+msgid ""
+"LDAP init: use_tls=%(use_tls)s\n"
+"tls_cacertfile=%(tls_cacertfile)s\n"
+"tls_cacertdir=%(tls_cacertdir)s\n"
+"tls_req_cert=%(tls_req_cert)s\n"
+"tls_avail=%(tls_avail)s\n"
+msgstr ""
+
+#: keystone/common/ldap/core.py:450
+msgid "Invalid TLS / LDAPS combination"
+msgstr ""
+
+#: keystone/common/ldap/core.py:454
+#, python-format
+msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available"
+msgstr ""
+
+#: keystone/common/ldap/core.py:464
+#, python-format
+msgid "tls_cacertfile %s not found or is not a file"
+msgstr ""
+
+#: keystone/common/ldap/core.py:476
+#, python-format
+msgid "tls_cacertdir %s not found or is not a directory"
+msgstr ""
+
+#: keystone/common/ldap/core.py:483
+#, python-format
+msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:497
+#, python-format
+msgid "LDAP bind: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:508
+#, python-format
+msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:514
+#, python-format
+msgid ""
+"LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, "
+"attrs=%(attrlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:567
+msgid ""
+"LDAP Server does not support paging. Disable paging in keystone.conf to "
+"avoid this message."
+msgstr ""
+
+#: keystone/common/ldap/core.py:584
+#, python-format
+msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:590
+#, python-format
+msgid "LDAP delete: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:595
+#, python-format
+msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:146
+#, python-format
+msgid "FakeLdap initialize url=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:156
+#, python-format
+msgid "FakeLdap bind dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:163
+#, python-format
+msgid "FakeLdap bind fail: dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:170
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:175
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s does not match"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:190
+#, python-format
+msgid "FakeLdap add item: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:193
+#, python-format
+msgid "FakeLdap add item failed: dn=%s is already in store."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:207 keystone/common/ldap/fakeldap.py:221
+#, python-format
+msgid "FakeLdap delete item: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:211 keystone/common/ldap/fakeldap.py:225
+#, python-format
+msgid "FakeLdap delete item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:240
+#, python-format
+msgid "FakeLdap modify item: dn=%(dn)s attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:245
+#, python-format
+msgid "FakeLdap modify item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:262
+#, python-format
+msgid "FakeLdap modify item failed: item has no attribute \"%s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:273
+#, python-format
+msgid ""
+"FakeLdap modify item failed: item has no attribute \"%(k)s\" with value "
+"\"%(v)s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:279
+#, python-format
+msgid "FakeLdap modify item failed: unknown command %s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:281
+#, python-format
+msgid "modify_s action %s not implemented"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:300
+#, python-format
+msgid "FakeLdap search at dn=%(dn)s scope=%(scope)s query=%(query)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:306
+msgid "FakeLdap search fail: dn not found for SCOPE_BASE"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:320
+#, python-format
+msgid "Search scope %s not implemented."
+msgstr ""
+
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
+#, python-format
+msgid "Got mysql server has gone away: %s"
+msgstr ""
+
+#: keystone/common/sql/legacy.py:188
+#, python-format
+msgid "Cannot migrate EC2 credential: %s"
+msgstr ""
+
+#: keystone/common/sql/migration.py:47
+msgid "version should be an integer"
+msgstr ""
+
+#: keystone/common/sql/nova.py:65
+#, python-format
+msgid "Create tenant %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:82
+#, python-format
+msgid "Create user %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:91
+#, python-format
+msgid "Add user %(user_id)s to tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:100
+#, python-format
+msgid "Ignoring existing role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:107
+#, python-format
+msgid "Create role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:117
+#, python-format
+msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:136
+#, python-format
+msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/identity/controllers.py:952
+#, python-format
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
+msgstr ""
+
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
+msgid "User not found in group"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:189
+#, python-format
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:334
+msgid "Changing Name not supported by LDAP"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:347
+#, python-format
+msgid "User %(user_id)s is already a member of group %(group_id)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:394
+#, python-format
+msgid "Failed to understand rule %(rule)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:404
+#, python-format
+msgid "No handler for matches of kind %s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:679
+#, python-format
+msgid "Failed to understand rule %(rule)r"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
+#: keystone/policy/backends/rules.py:93
+#, python-format
+msgid "enforce %(action)s: %(credentials)s"
+msgstr ""
+
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
+msgid "Token does not belong to specified tenant."
+msgstr ""
+
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
+msgstr ""
+
+#: keystone/token/backends/memcache.py:144
+#, python-format
+msgid ""
+"Successful set of token-index-list for user-key \"%(user_key)s\", "
+"#%(count)d records"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:154
+#, python-format
+msgid ""
+"Failed to set token-index-list for user-key \"%(user_key)s\". Attempt "
+"%(cas_retry)d of %(cas_retry_max)d"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:163
+msgid "Unable to add token user list"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:172
+msgid "Unable to add token to revocation list."
+msgstr ""
+
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
diff --git a/keystone/locale/vi_VN/LC_MESSAGES/keystone.po b/keystone/locale/vi_VN/LC_MESSAGES/keystone.po
index fd927b31..a7f3d30c 100644
--- a/keystone/locale/vi_VN/LC_MESSAGES/keystone.po
+++ b/keystone/locale/vi_VN/LC_MESSAGES/keystone.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Keystone\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2013-06-17 17:09+0000\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
"PO-Revision-Date: 2013-05-17 16:06+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
"Language-Team: Vietnamese (Viet Nam) "
@@ -16,7 +16,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.6\n"
+"Generated-By: Babel 1.3\n"
#: keystone/clean.py:23
#, python-format
@@ -38,62 +38,224 @@ msgstr ""
msgid "%(property_name)s is not a %(display_expected_type)s"
msgstr ""
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
#: keystone/test.py:117
#, python-format
msgid "Failed to checkout %s"
msgstr ""
-#: keystone/auth/controllers.py:72
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr ""
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr ""
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
#, python-format
msgid "Project is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:78 keystone/auth/plugins/password.py:39
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
#, python-format
msgid "Domain is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:84 keystone/auth/plugins/password.py:45
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
#, python-format
msgid "User is disabled: %s"
msgstr ""
-#: keystone/auth/controllers.py:265
+#: keystone/auth/controllers.py:262
msgid "Scoping to both domain and project is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:268
+#: keystone/auth/controllers.py:265
msgid "Scoping to both domain and trust is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:271
+#: keystone/auth/controllers.py:268
msgid "Scoping to both project and trust is not allowed"
msgstr ""
-#: keystone/auth/controllers.py:333
-#, python-format
-msgid "Unable to lookup user %s"
-msgstr ""
-
-#: keystone/auth/controllers.py:363
+#: keystone/auth/controllers.py:353
msgid "User not found"
msgstr ""
-#: keystone/auth/token_factory.py:81
-msgid "User have no access to project"
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
msgstr ""
-#: keystone/auth/token_factory.py:96
-msgid "User have no access to domain"
-msgstr ""
-
-#: keystone/auth/token_factory.py:314 keystone/token/controllers.py:121
-msgid "Unable to sign token."
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
+#, python-format
+msgid "Unable to lookup user %s"
msgstr ""
-#: keystone/auth/token_factory.py:317 keystone/token/controllers.py:124
-#, python-format
-msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
msgstr ""
#: keystone/catalog/core.py:38
@@ -120,18 +282,18 @@ msgstr ""
msgid "Unable to open template file %s"
msgstr ""
-#: keystone/common/cms.py:42
+#: keystone/common/cms.py:26
#, python-format
msgid "Verify error: %s"
msgstr ""
-#: keystone/common/cms.py:134
+#: keystone/common/cms.py:118
msgid ""
"Signing error: Unable to load certificate - ensure you've configured PKI "
"with 'keystone-manage pki_setup'"
msgstr ""
-#: keystone/common/cms.py:138
+#: keystone/common/cms.py:122
#, python-format
msgid "Signing error: %s"
msgstr ""
@@ -150,31 +312,31 @@ msgstr ""
msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
msgstr ""
-#: keystone/common/controller.py:26
+#: keystone/common/controller.py:25
msgid "RBAC: Invalid token"
msgstr ""
-#: keystone/common/controller.py:36 keystone/common/controller.py:57
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
msgid "RBAC: Invalid user"
msgstr ""
-#: keystone/common/controller.py:42
+#: keystone/common/controller.py:45
msgid "RBAC: Proceeding without project"
msgstr ""
-#: keystone/common/controller.py:62
+#: keystone/common/controller.py:65
msgid "RBAC: Proceeding without tenant"
msgstr ""
-#: keystone/common/controller.py:92 keystone/common/controller.py:144
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
msgid "RBAC: Bypassing authorization"
msgstr ""
-#: keystone/common/controller.py:101 keystone/common/controller.py:142
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
msgid "RBAC: Authorization granted"
msgstr ""
-#: keystone/common/controller.py:131
+#: keystone/common/controller.py:134
#, python-format
msgid "RBAC: Adding query filter params (%s)"
msgstr ""
@@ -183,33 +345,69 @@ msgstr ""
msgid "Invalid token in normalize_domain_id"
msgstr ""
-#: keystone/common/utils.py:232
+#: keystone/common/utils.py:233
msgid ""
"Error setting up the debug environment. Verify that the option --debug-"
"url has the format <host>:<port> and that a debugger processes is "
"listening on that port."
msgstr ""
-#: keystone/common/wsgi.py:162
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
#, python-format
msgid "arg_dict: %s"
msgstr ""
-#: keystone/common/wsgi.py:186
+#: keystone/common/wsgi.py:243
#, python-format
msgid "Authorization failed. %(exception)s from %(remote_addr)s"
msgstr ""
-#: keystone/common/wsgi.py:429
+#: keystone/common/wsgi.py:487
msgid "The resource could not be found."
msgstr ""
-#: keystone/common/wsgi_server.py:72
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
#, python-format
msgid "Starting %(arg0)s on %(host)s:%(port)s"
msgstr ""
-#: keystone/common/wsgi_server.py:132
+#: keystone/common/environment/eventlet_server.py:113
msgid "Server error"
msgstr ""
@@ -242,13 +440,13 @@ msgid ""
"\"%(attr_map)s\" must use one of %(keys)s."
msgstr ""
-#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:596
-#: keystone/identity/backends/kvs.py:624
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
#, python-format
msgid "Duplicate name, %s."
msgstr ""
-#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:589
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
#, python-format
msgid "Duplicate ID, %s."
msgstr ""
@@ -436,12 +634,16 @@ msgstr ""
msgid "Search scope %s not implemented."
msgstr ""
-#: keystone/common/sql/core.py:205
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
#, python-format
msgid "Got mysql server has gone away: %s"
msgstr ""
-#: keystone/common/sql/legacy.py:180
+#: keystone/common/sql/legacy.py:188
#, python-format
msgid "Cannot migrate EC2 credential: %s"
msgstr ""
@@ -450,76 +652,68 @@ msgstr ""
msgid "version should be an integer"
msgstr ""
-#: keystone/common/sql/nova.py:62
+#: keystone/common/sql/nova.py:65
#, python-format
msgid "Create tenant %s"
msgstr ""
-#: keystone/common/sql/nova.py:79
+#: keystone/common/sql/nova.py:82
#, python-format
msgid "Create user %s"
msgstr ""
-#: keystone/common/sql/nova.py:88
+#: keystone/common/sql/nova.py:91
#, python-format
msgid "Add user %(user_id)s to tenant %(tenant_id)s"
msgstr ""
-#: keystone/common/sql/nova.py:97
+#: keystone/common/sql/nova.py:100
#, python-format
msgid "Ignoring existing role %s"
msgstr ""
-#: keystone/common/sql/nova.py:104
+#: keystone/common/sql/nova.py:107
#, python-format
msgid "Create role %s"
msgstr ""
-#: keystone/common/sql/nova.py:114
+#: keystone/common/sql/nova.py:117
#, python-format
msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
msgstr ""
-#: keystone/common/sql/nova.py:133
+#: keystone/common/sql/nova.py:136
#, python-format
msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
msgstr ""
-#: keystone/identity/backends/kvs.py:250 keystone/identity/backends/kvs.py:259
-msgid "User not found in group"
-msgstr ""
-
-#: keystone/identity/backends/sql.py:425
+#: keystone/identity/controllers.py:952
#, python-format
-msgid "Cannot remove role that has not been granted, %s"
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:82
-#, python-format
-msgid "Expected dict or list: %s"
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
+msgid "User not found in group"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:681
+#: keystone/identity/backends/ldap.py:189
#, python-format
-msgid "Role %s not found"
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
msgstr ""
-#: keystone/identity/backends/ldap/core.py:898
+#: keystone/identity/backends/ldap.py:334
msgid "Changing Name not supported by LDAP"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:911
+#: keystone/identity/backends/ldap.py:347
#, python-format
msgid "User %(user_id)s is already a member of group %(group_id)s"
msgstr ""
-#: keystone/identity/backends/ldap/core.py:954
-#, python-format
-msgid ""
-"Group member '%(user_dn)s' not found in '%(group_dn)s'. The user should "
-"be removed from the group. The user will be ignored."
-msgstr ""
-
#: keystone/openstack/common/policy.py:394
#, python-format
msgid "Failed to understand rule %(rule)s"
@@ -535,21 +729,56 @@ msgstr ""
msgid "Failed to understand rule %(rule)r"
msgstr ""
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
#: keystone/policy/backends/rules.py:93
#, python-format
msgid "enforce %(action)s: %(credentials)s"
msgstr ""
-#: keystone/token/controllers.py:465 keystone/token/controllers.py:468
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
msgid "Token does not belong to specified tenant."
msgstr ""
-#: keystone/token/controllers.py:475
-msgid "Non-default domain is not supported"
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
msgstr ""
-#: keystone/token/controllers.py:483
-msgid "Domain scoped token is not supported"
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
msgstr ""
#: keystone/token/backends/memcache.py:144
@@ -574,3 +803,54 @@ msgstr ""
msgid "Unable to add token to revocation list."
msgstr ""
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
+#~ msgid "User have no access to project"
+#~ msgstr ""
+
+#~ msgid "User have no access to domain"
+#~ msgstr ""
+
+#~ msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+#~ msgstr ""
+
diff --git a/keystone/locale/zh_CN/LC_MESSAGES/keystone.po b/keystone/locale/zh_CN/LC_MESSAGES/keystone.po
index a0f65cdd..8d69a376 100644
--- a/keystone/locale/zh_CN/LC_MESSAGES/keystone.po
+++ b/keystone/locale/zh_CN/LC_MESSAGES/keystone.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Keystone\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2013-06-17 17:09+0000\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
"PO-Revision-Date: 2013-05-21 06:08+0000\n"
"Last-Translator: daisy.ycguo <daisy.ycguo@gmail.com>\n"
"Language-Team: Chinese (China) "
@@ -16,7 +16,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.6\n"
+"Generated-By: Babel 1.3\n"
#: keystone/clean.py:23
#, python-format
@@ -38,63 +38,225 @@ msgstr "%(property_name)s ä¸åº”该超过 %(max_length)s 个字符。"
msgid "%(property_name)s is not a %(display_expected_type)s"
msgstr ""
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
#: keystone/test.py:117
#, python-format
msgid "Failed to checkout %s"
msgstr "未能检出 %s"
-#: keystone/auth/controllers.py:72
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr "无法除去尚未授予的角色 %s"
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr "找ä¸åˆ°è§’色 %s"
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
#, python-format
msgid "Project is disabled: %s"
msgstr "项目已ç¦ç”¨ï¼š%s"
-#: keystone/auth/controllers.py:78 keystone/auth/plugins/password.py:39
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
#, python-format
msgid "Domain is disabled: %s"
msgstr "域已ç¦ç”¨ï¼š%s"
-#: keystone/auth/controllers.py:84 keystone/auth/plugins/password.py:45
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
#, python-format
msgid "User is disabled: %s"
msgstr "用户已ç¦ç”¨ï¼š%s"
-#: keystone/auth/controllers.py:265
+#: keystone/auth/controllers.py:262
msgid "Scoping to both domain and project is not allowed"
msgstr "ä¸å…许åŒæ—¶å°†ä½œç”¨åŸŸé™å®šåˆ°åŸŸå’Œé¡¹ç›®"
-#: keystone/auth/controllers.py:268
+#: keystone/auth/controllers.py:265
msgid "Scoping to both domain and trust is not allowed"
msgstr "ä¸å…许åŒæ—¶å°†ä½œç”¨åŸŸé™å®šåˆ°åŸŸå’Œä¿¡ä»»"
-#: keystone/auth/controllers.py:271
+#: keystone/auth/controllers.py:268
msgid "Scoping to both project and trust is not allowed"
msgstr "ä¸å…许åŒæ—¶å°†ä½œç”¨åŸŸé™å®šåˆ°é¡¹ç›®å’Œä¿¡ä»»"
-#: keystone/auth/controllers.py:333
-#, python-format
-msgid "Unable to lookup user %s"
-msgstr "无法查找用户 %s"
-
-#: keystone/auth/controllers.py:363
+#: keystone/auth/controllers.py:353
msgid "User not found"
msgstr "找ä¸åˆ°ç”¨æˆ·"
-#: keystone/auth/token_factory.py:81
-msgid "User have no access to project"
-msgstr "用户对项目没有任何访问æƒé™"
-
-#: keystone/auth/token_factory.py:96
-msgid "User have no access to domain"
-msgstr "用户对域没有任何访问æƒé™"
-
-#: keystone/auth/token_factory.py:314 keystone/token/controllers.py:121
-msgid "Unable to sign token."
-msgstr "无法对令牌进行签å。"
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
+msgstr ""
-#: keystone/auth/token_factory.py:317 keystone/token/controllers.py:124
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
#, python-format
-msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
-msgstr "token_format 的值 %s 无效。å…许值是 PKI 或 UUID。"
+msgid "Unable to lookup user %s"
+msgstr "无法查找用户 %s"
+
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
+msgstr ""
#: keystone/catalog/core.py:38
#, python-format
@@ -120,18 +282,18 @@ msgstr "端点 %s çš„æ ¼å¼ä¸æ­£ç¡® - æ ¼å¼ä¸å®Œæ•´ï¼ˆæ‚¨é—æ¼äº†ç±»åž‹é€šçŸ
msgid "Unable to open template file %s"
msgstr "无法打开模æ¿æ–‡ä»¶ %s"
-#: keystone/common/cms.py:42
+#: keystone/common/cms.py:26
#, python-format
msgid "Verify error: %s"
msgstr "å‘生验è¯é”™è¯¯ï¼š%s"
-#: keystone/common/cms.py:134
+#: keystone/common/cms.py:118
msgid ""
"Signing error: Unable to load certificate - ensure you've configured PKI "
"with 'keystone-manage pki_setup'"
msgstr "å‘生签å错误:无法装入è¯ä¹¦ - 请确ä¿æ‚¨å·²ä½¿ç”¨â€œkeystone-manage pki_setupâ€é…ç½® PKI"
-#: keystone/common/cms.py:138
+#: keystone/common/cms.py:122
#, python-format
msgid "Signing error: %s"
msgstr "å‘生签å错误:%s"
@@ -150,31 +312,31 @@ msgstr "系统日志工具无效"
msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
msgstr ""
-#: keystone/common/controller.py:26
+#: keystone/common/controller.py:25
msgid "RBAC: Invalid token"
msgstr "RBAC:令牌无效"
-#: keystone/common/controller.py:36 keystone/common/controller.py:57
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
msgid "RBAC: Invalid user"
msgstr "RBAC:用户无效"
-#: keystone/common/controller.py:42
+#: keystone/common/controller.py:45
msgid "RBAC: Proceeding without project"
msgstr "RBAC:正在没有项目的情况下继续"
-#: keystone/common/controller.py:62
+#: keystone/common/controller.py:65
msgid "RBAC: Proceeding without tenant"
msgstr "RBAC:正在没有租户的情况下继续"
-#: keystone/common/controller.py:92 keystone/common/controller.py:144
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
msgid "RBAC: Bypassing authorization"
msgstr "RBAC:正在绕过授æƒ"
-#: keystone/common/controller.py:101 keystone/common/controller.py:142
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
msgid "RBAC: Authorization granted"
msgstr "RBAC:已授予æƒé™"
-#: keystone/common/controller.py:131
+#: keystone/common/controller.py:134
#, python-format
msgid "RBAC: Adding query filter params (%s)"
msgstr "RBAC:正在添加查询过滤器å‚æ•° (%s)"
@@ -183,33 +345,69 @@ msgstr "RBAC:正在添加查询过滤器å‚æ•° (%s)"
msgid "Invalid token in normalize_domain_id"
msgstr "normalize_domain_id 中的令牌无效"
-#: keystone/common/utils.py:232
+#: keystone/common/utils.py:233
msgid ""
"Error setting up the debug environment. Verify that the option --debug-"
"url has the format <host>:<port> and that a debugger processes is "
"listening on that port."
msgstr ""
-#: keystone/common/wsgi.py:162
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
#, python-format
msgid "arg_dict: %s"
msgstr "arg_dict:%s"
-#: keystone/common/wsgi.py:186
+#: keystone/common/wsgi.py:243
#, fuzzy, python-format
msgid "Authorization failed. %(exception)s from %(remote_addr)s"
msgstr "授æƒå¤±è´¥ã€‚%s æ¥è‡ª %s"
-#: keystone/common/wsgi.py:429
+#: keystone/common/wsgi.py:487
msgid "The resource could not be found."
msgstr "找ä¸åˆ°è¯¥èµ„æºã€‚"
-#: keystone/common/wsgi_server.py:72
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
#, python-format
msgid "Starting %(arg0)s on %(host)s:%(port)s"
msgstr "正在 %(host)s:%(port)s 上å¯åŠ¨ %(arg0)s"
-#: keystone/common/wsgi_server.py:132
+#: keystone/common/environment/eventlet_server.py:113
msgid "Server error"
msgstr "æœåŠ¡å™¨é”™è¯¯"
@@ -242,13 +440,13 @@ msgid ""
"\"%(attr_map)s\" must use one of %(keys)s."
msgstr ""
-#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:596
-#: keystone/identity/backends/kvs.py:624
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
#, python-format
msgid "Duplicate name, %s."
msgstr "å称 %s é‡å¤ã€‚"
-#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:589
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
#, python-format
msgid "Duplicate ID, %s."
msgstr "标识 %s é‡å¤ã€‚"
@@ -436,12 +634,16 @@ msgstr "FakeLdap search 失败:对于 SCOPE_BASE,找ä¸åˆ° dn"
msgid "Search scope %s not implemented."
msgstr "未实现æœç´¢èŒƒå›´ %s。"
-#: keystone/common/sql/core.py:205
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
#, python-format
msgid "Got mysql server has gone away: %s"
msgstr "mysql æœåŠ¡å™¨å·²ä¸å­˜åœ¨ï¼š%s"
-#: keystone/common/sql/legacy.py:180
+#: keystone/common/sql/legacy.py:188
#, python-format
msgid "Cannot migrate EC2 credential: %s"
msgstr "无法è¿ç§» EC2 凭è¯ï¼š%s"
@@ -450,76 +652,68 @@ msgstr "无法è¿ç§» EC2 凭è¯ï¼š%s"
msgid "version should be an integer"
msgstr "版本应该为整数"
-#: keystone/common/sql/nova.py:62
+#: keystone/common/sql/nova.py:65
#, python-format
msgid "Create tenant %s"
msgstr "请创建租户 %s"
-#: keystone/common/sql/nova.py:79
+#: keystone/common/sql/nova.py:82
#, python-format
msgid "Create user %s"
msgstr "请创建用户 %s"
-#: keystone/common/sql/nova.py:88
+#: keystone/common/sql/nova.py:91
#, fuzzy, python-format
msgid "Add user %(user_id)s to tenant %(tenant_id)s"
msgstr "请将用户 %s 添加至租户 %s"
-#: keystone/common/sql/nova.py:97
+#: keystone/common/sql/nova.py:100
#, python-format
msgid "Ignoring existing role %s"
msgstr "正在忽略现有角色 %s"
-#: keystone/common/sql/nova.py:104
+#: keystone/common/sql/nova.py:107
#, python-format
msgid "Create role %s"
msgstr "请创建角色 %s"
-#: keystone/common/sql/nova.py:114
+#: keystone/common/sql/nova.py:117
#, fuzzy, python-format
msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
msgstr "请将角色 %s 分é…给用户 %s(在租户 %s 上)"
-#: keystone/common/sql/nova.py:133
+#: keystone/common/sql/nova.py:136
#, fuzzy, python-format
msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
msgstr "正在为用户 %s 和租户 %s 创建 ec2 凭è¯"
-#: keystone/identity/backends/kvs.py:250 keystone/identity/backends/kvs.py:259
+#: keystone/identity/controllers.py:952
+#, python-format
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
+msgstr ""
+
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
msgid "User not found in group"
msgstr "在组中找ä¸åˆ°ç”¨æˆ·"
-#: keystone/identity/backends/sql.py:425
-#, python-format
-msgid "Cannot remove role that has not been granted, %s"
-msgstr "无法除去尚未授予的角色 %s"
-
-#: keystone/identity/backends/ldap/core.py:82
+#: keystone/identity/backends/ldap.py:189
#, python-format
-msgid "Expected dict or list: %s"
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
msgstr ""
-#: keystone/identity/backends/ldap/core.py:681
-#, python-format
-msgid "Role %s not found"
-msgstr "找ä¸åˆ°è§’色 %s"
-
-#: keystone/identity/backends/ldap/core.py:898
+#: keystone/identity/backends/ldap.py:334
msgid "Changing Name not supported by LDAP"
msgstr "更改å称ä¸å— LDAP 支æŒ"
-#: keystone/identity/backends/ldap/core.py:911
+#: keystone/identity/backends/ldap.py:347
#, fuzzy, python-format
msgid "User %(user_id)s is already a member of group %(group_id)s"
msgstr "用户 %s 已是组 %s çš„æˆå‘˜"
-#: keystone/identity/backends/ldap/core.py:954
-#, python-format
-msgid ""
-"Group member '%(user_dn)s' not found in '%(group_dn)s'. The user should "
-"be removed from the group. The user will be ignored."
-msgstr ""
-
#: keystone/openstack/common/policy.py:394
#, python-format
msgid "Failed to understand rule %(rule)s"
@@ -535,22 +729,57 @@ msgstr "对于类型为 %s 的匹é…项,ä¸å­˜åœ¨ä»»ä½•å¤„ç†ç¨‹åº"
msgid "Failed to understand rule %(rule)r"
msgstr "未能ç†è§£è§„则 %(rule)r"
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
#: keystone/policy/backends/rules.py:93
#, python-format
msgid "enforce %(action)s: %(credentials)s"
msgstr ""
-#: keystone/token/controllers.py:465 keystone/token/controllers.py:468
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
msgid "Token does not belong to specified tenant."
msgstr "令牌ä¸å±žäºŽæŒ‡å®šçš„租户。"
-#: keystone/token/controllers.py:475
-msgid "Non-default domain is not supported"
-msgstr "éžç¼ºçœåŸŸä¸å—支æŒ"
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
+msgstr ""
-#: keystone/token/controllers.py:483
-msgid "Domain scoped token is not supported"
-msgstr "作用域é™å®šåˆ°åŸŸçš„令牌ä¸å—支æŒ"
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
+msgstr ""
#: keystone/token/backends/memcache.py:144
#, python-format
@@ -574,3 +803,54 @@ msgstr ""
msgid "Unable to add token to revocation list."
msgstr "无法将令牌添加至撤销列表。"
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr "无法对令牌进行签å。"
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr "éžç¼ºçœåŸŸä¸å—支æŒ"
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr "作用域é™å®šåˆ°åŸŸçš„令牌ä¸å—支æŒ"
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
+#~ msgid "User have no access to project"
+#~ msgstr "用户对项目没有任何访问æƒé™"
+
+#~ msgid "User have no access to domain"
+#~ msgstr "用户对域没有任何访问æƒé™"
+
+#~ msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+#~ msgstr "token_format 的值 %s 无效。å…许值是 PKI 或 UUID。"
+
diff --git a/keystone/locale/zh_HK/LC_MESSAGES/keystone.po b/keystone/locale/zh_HK/LC_MESSAGES/keystone.po
new file mode 100644
index 00000000..be48e5f5
--- /dev/null
+++ b/keystone/locale/zh_HK/LC_MESSAGES/keystone.po
@@ -0,0 +1,847 @@
+# Chinese (Traditional, Hong Kong SAR China) translations for keystone.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the keystone project.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: Keystone\n"
+"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
+"PO-Revision-Date: 2013-07-29 22:01+0000\n"
+"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
+"Language-Team: Chinese (Hong Kong) "
+"(http://www.transifex.com/projects/p/openstack/language/zh_HK/)\n"
+"Plural-Forms: nplurals=1; plural=0\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: keystone/clean.py:23
+#, python-format
+msgid "%s cannot be empty."
+msgstr ""
+
+#: keystone/clean.py:25
+#, python-format
+msgid "%(property_name)s cannot be less than %(min_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:29
+#, python-format
+msgid "%(property_name)s should not be greater than %(max_length)s characters."
+msgstr ""
+
+#: keystone/clean.py:36
+#, python-format
+msgid "%(property_name)s is not a %(display_expected_type)s"
+msgstr ""
+
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
+#: keystone/test.py:117
+#, python-format
+msgid "Failed to checkout %s"
+msgstr ""
+
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr ""
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr ""
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
+#, python-format
+msgid "Project is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
+#, python-format
+msgid "Domain is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
+#, python-format
+msgid "User is disabled: %s"
+msgstr ""
+
+#: keystone/auth/controllers.py:262
+msgid "Scoping to both domain and project is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:265
+msgid "Scoping to both domain and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:268
+msgid "Scoping to both project and trust is not allowed"
+msgstr ""
+
+#: keystone/auth/controllers.py:353
+msgid "User not found"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
+msgstr ""
+
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
+#, python-format
+msgid "Unable to lookup user %s"
+msgstr ""
+
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
+msgstr ""
+
+#: keystone/catalog/core.py:38
+#, python-format
+msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s"
+msgstr ""
+
+#: keystone/catalog/core.py:43
+#, python-format
+msgid ""
+"Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing "
+"brackets ?)"
+msgstr ""
+
+#: keystone/catalog/core.py:49
+#, python-format
+msgid ""
+"Malformed endpoint %s - incomplete format (are you "
+"missing a type notifier ?)"
+msgstr ""
+
+#: keystone/catalog/backends/templated.py:109
+#, python-format
+msgid "Unable to open template file %s"
+msgstr ""
+
+#: keystone/common/cms.py:26
+#, python-format
+msgid "Verify error: %s"
+msgstr ""
+
+#: keystone/common/cms.py:118
+msgid ""
+"Signing error: Unable to load certificate - ensure you've configured PKI "
+"with 'keystone-manage pki_setup'"
+msgstr ""
+
+#: keystone/common/cms.py:122
+#, python-format
+msgid "Signing error: %s"
+msgstr ""
+
+#: keystone/common/config.py:89
+#, python-format
+msgid "Unable to locate specified logging config file: %s"
+msgstr ""
+
+#: keystone/common/config.py:107
+msgid "Invalid syslog facility"
+msgstr ""
+
+#: keystone/common/controller.py:18
+#, python-format
+msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
+msgstr ""
+
+#: keystone/common/controller.py:25
+msgid "RBAC: Invalid token"
+msgstr ""
+
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
+msgid "RBAC: Invalid user"
+msgstr ""
+
+#: keystone/common/controller.py:45
+msgid "RBAC: Proceeding without project"
+msgstr ""
+
+#: keystone/common/controller.py:65
+msgid "RBAC: Proceeding without tenant"
+msgstr ""
+
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
+msgid "RBAC: Bypassing authorization"
+msgstr ""
+
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
+msgid "RBAC: Authorization granted"
+msgstr ""
+
+#: keystone/common/controller.py:134
+#, python-format
+msgid "RBAC: Adding query filter params (%s)"
+msgstr ""
+
+#: keystone/common/controller.py:322
+msgid "Invalid token in normalize_domain_id"
+msgstr ""
+
+#: keystone/common/utils.py:233
+msgid ""
+"Error setting up the debug environment. Verify that the option --debug-"
+"url has the format <host>:<port> and that a debugger processes is "
+"listening on that port."
+msgstr ""
+
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
+#, python-format
+msgid "arg_dict: %s"
+msgstr ""
+
+#: keystone/common/wsgi.py:243
+#, python-format
+msgid "Authorization failed. %(exception)s from %(remote_addr)s"
+msgstr ""
+
+#: keystone/common/wsgi.py:487
+msgid "The resource could not be found."
+msgstr ""
+
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
+#, python-format
+msgid "Starting %(arg0)s on %(host)s:%(port)s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:113
+msgid "Server error"
+msgstr ""
+
+#: keystone/common/ldap/core.py:79
+#, python-format
+msgid "Invalid LDAP deref option: %s. Choose one of: "
+msgstr ""
+
+#: keystone/common/ldap/core.py:87
+#, python-format
+msgid "Invalid LDAP TLS certs option: %(option). Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:99
+#, python-format
+msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:189
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%s\". Format must be "
+"<ldap_attribute>:<keystone_attribute>"
+msgstr ""
+
+#: keystone/common/ldap/core.py:195
+#, python-format
+msgid ""
+"Invalid additional attribute mapping: \"%(item)s\". Value "
+"\"%(attr_map)s\" must use one of %(keys)s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
+#, python-format
+msgid "Duplicate name, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
+#, python-format
+msgid "Duplicate ID, %s."
+msgstr ""
+
+#: keystone/common/ldap/core.py:294
+#, python-format
+msgid "LDAP %s create"
+msgstr ""
+
+#: keystone/common/ldap/core.py:372
+#, python-format
+msgid "LDAP %s update"
+msgstr ""
+
+#: keystone/common/ldap/core.py:405
+#, python-format
+msgid "LDAP %s delete"
+msgstr ""
+
+#: keystone/common/ldap/core.py:430
+#, python-format
+msgid "LDAP init: url=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:431
+#, python-format
+msgid ""
+"LDAP init: use_tls=%(use_tls)s\n"
+"tls_cacertfile=%(tls_cacertfile)s\n"
+"tls_cacertdir=%(tls_cacertdir)s\n"
+"tls_req_cert=%(tls_req_cert)s\n"
+"tls_avail=%(tls_avail)s\n"
+msgstr ""
+
+#: keystone/common/ldap/core.py:450
+msgid "Invalid TLS / LDAPS combination"
+msgstr ""
+
+#: keystone/common/ldap/core.py:454
+#, python-format
+msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available"
+msgstr ""
+
+#: keystone/common/ldap/core.py:464
+#, python-format
+msgid "tls_cacertfile %s not found or is not a file"
+msgstr ""
+
+#: keystone/common/ldap/core.py:476
+#, python-format
+msgid "tls_cacertdir %s not found or is not a directory"
+msgstr ""
+
+#: keystone/common/ldap/core.py:483
+#, python-format
+msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:497
+#, python-format
+msgid "LDAP bind: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:508
+#, python-format
+msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:514
+#, python-format
+msgid ""
+"LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, "
+"attrs=%(attrlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:567
+msgid ""
+"LDAP Server does not support paging. Disable paging in keystone.conf to "
+"avoid this message."
+msgstr ""
+
+#: keystone/common/ldap/core.py:584
+#, python-format
+msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:590
+#, python-format
+msgid "LDAP delete: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/core.py:595
+#, python-format
+msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:146
+#, python-format
+msgid "FakeLdap initialize url=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:156
+#, python-format
+msgid "FakeLdap bind dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:163
+#, python-format
+msgid "FakeLdap bind fail: dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:170
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s not found"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:175
+#, python-format
+msgid "FakeLdap bind fail: password for dn=%s does not match"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:190
+#, python-format
+msgid "FakeLdap add item: dn=%(dn)s, attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:193
+#, python-format
+msgid "FakeLdap add item failed: dn=%s is already in store."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:207 keystone/common/ldap/fakeldap.py:221
+#, python-format
+msgid "FakeLdap delete item: dn=%s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:211 keystone/common/ldap/fakeldap.py:225
+#, python-format
+msgid "FakeLdap delete item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:240
+#, python-format
+msgid "FakeLdap modify item: dn=%(dn)s attrs=%(attrs)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:245
+#, python-format
+msgid "FakeLdap modify item failed: dn=%s not found."
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:262
+#, python-format
+msgid "FakeLdap modify item failed: item has no attribute \"%s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:273
+#, python-format
+msgid ""
+"FakeLdap modify item failed: item has no attribute \"%(k)s\" with value "
+"\"%(v)s\" to delete"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:279
+#, python-format
+msgid "FakeLdap modify item failed: unknown command %s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:281
+#, python-format
+msgid "modify_s action %s not implemented"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:300
+#, python-format
+msgid "FakeLdap search at dn=%(dn)s scope=%(scope)s query=%(query)s"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:306
+msgid "FakeLdap search fail: dn not found for SCOPE_BASE"
+msgstr ""
+
+#: keystone/common/ldap/fakeldap.py:320
+#, python-format
+msgid "Search scope %s not implemented."
+msgstr ""
+
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
+#, python-format
+msgid "Got mysql server has gone away: %s"
+msgstr ""
+
+#: keystone/common/sql/legacy.py:188
+#, python-format
+msgid "Cannot migrate EC2 credential: %s"
+msgstr ""
+
+#: keystone/common/sql/migration.py:47
+msgid "version should be an integer"
+msgstr ""
+
+#: keystone/common/sql/nova.py:65
+#, python-format
+msgid "Create tenant %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:82
+#, python-format
+msgid "Create user %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:91
+#, python-format
+msgid "Add user %(user_id)s to tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:100
+#, python-format
+msgid "Ignoring existing role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:107
+#, python-format
+msgid "Create role %s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:117
+#, python-format
+msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/common/sql/nova.py:136
+#, python-format
+msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
+msgstr ""
+
+#: keystone/identity/controllers.py:952
+#, python-format
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
+msgstr ""
+
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
+msgid "User not found in group"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:189
+#, python-format
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:334
+msgid "Changing Name not supported by LDAP"
+msgstr ""
+
+#: keystone/identity/backends/ldap.py:347
+#, python-format
+msgid "User %(user_id)s is already a member of group %(group_id)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:394
+#, python-format
+msgid "Failed to understand rule %(rule)s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:404
+#, python-format
+msgid "No handler for matches of kind %s"
+msgstr ""
+
+#: keystone/openstack/common/policy.py:679
+#, python-format
+msgid "Failed to understand rule %(rule)r"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
+#: keystone/policy/backends/rules.py:93
+#, python-format
+msgid "enforce %(action)s: %(credentials)s"
+msgstr ""
+
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
+msgid "Token does not belong to specified tenant."
+msgstr ""
+
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
+msgstr ""
+
+#: keystone/token/backends/memcache.py:144
+#, python-format
+msgid ""
+"Successful set of token-index-list for user-key \"%(user_key)s\", "
+"#%(count)d records"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:154
+#, python-format
+msgid ""
+"Failed to set token-index-list for user-key \"%(user_key)s\". Attempt "
+"%(cas_retry)d of %(cas_retry_max)d"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:163
+msgid "Unable to add token user list"
+msgstr ""
+
+#: keystone/token/backends/memcache.py:172
+msgid "Unable to add token to revocation list."
+msgstr ""
+
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
diff --git a/keystone/locale/zh_TW/LC_MESSAGES/keystone.po b/keystone/locale/zh_TW/LC_MESSAGES/keystone.po
index eae36832..45af1114 100644
--- a/keystone/locale/zh_TW/LC_MESSAGES/keystone.po
+++ b/keystone/locale/zh_TW/LC_MESSAGES/keystone.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Keystone\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2013-06-17 17:09+0000\n"
+"POT-Creation-Date: 2013-08-02 17:05+0000\n"
"PO-Revision-Date: 2013-05-22 03:11+0000\n"
"Last-Translator: daisy.ycguo <daisy.ycguo@gmail.com>\n"
"Language-Team: Chinese (Taiwan) "
@@ -16,7 +16,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.6\n"
+"Generated-By: Babel 1.3\n"
#: keystone/clean.py:23
#, python-format
@@ -38,63 +38,225 @@ msgstr "%(property_name)s ä¸æ‡‰è¶…éŽ %(max_length)s 個字元。"
msgid "%(property_name)s is not a %(display_expected_type)s"
msgstr ""
+#: keystone/exception.py:48
+msgid "missing exception kwargs (programmer error)"
+msgstr ""
+
+#: keystone/exception.py:65
+#, python-format
+msgid ""
+"Expecting to find %(attribute)s in %(target)s. The server could not "
+"comply with the request since it is either malformed or otherwise "
+"incorrect. The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:74
+#, python-format
+msgid ""
+"String length exceeded.The length of string '%(string)s' exceeded the "
+"limit of column %(type)s(CHAR(%(length)d))."
+msgstr ""
+
+#: keystone/exception.py:80
+#, python-format
+msgid ""
+"Request attribute %(attribute)s must be less than or equal to %(size)i. "
+"The server could not comply with the request because the attribute size "
+"is invalid (too large). The client is assumed to be in error."
+msgstr ""
+
+#: keystone/exception.py:101
+msgid "The request you have made requires authentication."
+msgstr ""
+
+#: keystone/exception.py:107
+msgid "Authentication plugin error."
+msgstr ""
+
+#: keystone/exception.py:115
+msgid "Attempted to authenticate with an unsupported method."
+msgstr ""
+
+#: keystone/exception.py:123
+msgid "Additional authentications steps required."
+msgstr ""
+
+#: keystone/exception.py:131
+msgid "You are not authorized to perform the requested action."
+msgstr ""
+
+#: keystone/exception.py:138
+#, python-format
+msgid "You are not authorized to perform the requested action, %(action)s."
+msgstr ""
+
+#: keystone/exception.py:143
+#, python-format
+msgid "Could not find, %(target)s."
+msgstr ""
+
+#: keystone/exception.py:149
+#, python-format
+msgid "Could not find endpoint, %(endpoint_id)s."
+msgstr ""
+
+#: keystone/exception.py:156
+msgid "An unhandled exception has occurred: Could not find metadata."
+msgstr ""
+
+#: keystone/exception.py:161
+#, python-format
+msgid "Could not find policy, %(policy_id)s."
+msgstr ""
+
+#: keystone/exception.py:165
+#, python-format
+msgid "Could not find role, %(role_id)s."
+msgstr ""
+
+#: keystone/exception.py:169
+#, python-format
+msgid "Could not find service, %(service_id)s."
+msgstr ""
+
+#: keystone/exception.py:173
+#, python-format
+msgid "Could not find domain, %(domain_id)s."
+msgstr ""
+
+#: keystone/exception.py:177
+#, python-format
+msgid "Could not find project, %(project_id)s."
+msgstr ""
+
+#: keystone/exception.py:181
+#, python-format
+msgid "Could not find token, %(token_id)s."
+msgstr ""
+
+#: keystone/exception.py:185
+#, python-format
+msgid "Could not find user, %(user_id)s."
+msgstr ""
+
+#: keystone/exception.py:189
+#, python-format
+msgid "Could not find group, %(group_id)s."
+msgstr ""
+
+#: keystone/exception.py:193
+#, python-format
+msgid "Could not find trust, %(trust_id)s."
+msgstr ""
+
+#: keystone/exception.py:197
+#, python-format
+msgid "Could not find credential, %(credential_id)s."
+msgstr ""
+
+#: keystone/exception.py:201
+#, python-format
+msgid "Could not find version, %(version)s."
+msgstr ""
+
+#: keystone/exception.py:205
+#, python-format
+msgid "Conflict occurred attempting to store %(type)s. %(details)s"
+msgstr ""
+
+#: keystone/exception.py:212
+msgid "Request is too large."
+msgstr ""
+
+#: keystone/exception.py:218
+#, python-format
+msgid ""
+"An unexpected error prevented the server from fulfilling your request. "
+"%(exception)s"
+msgstr ""
+
+#: keystone/exception.py:225
+#, python-format
+msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
+msgstr ""
+
+#: keystone/exception.py:230
+msgid "The action you have requested has not been implemented."
+msgstr ""
+
+#: keystone/exception.py:237
+#, python-format
+msgid "The Keystone paste configuration file %(config_file)s could not be found."
+msgstr ""
+
#: keystone/test.py:117
#, python-format
msgid "Failed to checkout %s"
msgstr "無法移出 %s"
-#: keystone/auth/controllers.py:72
+#: keystone/assignment/core.py:529
+#, python-format
+msgid "Expected dict or list: %s"
+msgstr ""
+
+#: keystone/assignment/backends/kvs.py:138
+#: keystone/assignment/backends/sql.py:285
+#, python-format
+msgid "Cannot remove role that has not been granted, %s"
+msgstr "無法移除尚未授權的角色,%s"
+
+#: keystone/assignment/backends/ldap.py:418
+#, python-format
+msgid "Role %s not found"
+msgstr "找ä¸åˆ°è§’色 %s"
+
+#: keystone/assignment/backends/sql.py:114
+msgid "Inherited roles can only be assigned to domains"
+msgstr ""
+
+#: keystone/auth/controllers.py:71
#, python-format
msgid "Project is disabled: %s"
msgstr "å·²åœç”¨å°ˆæ¡ˆï¼š%s"
-#: keystone/auth/controllers.py:78 keystone/auth/plugins/password.py:39
+#: keystone/auth/controllers.py:77 keystone/auth/plugins/password.py:38
#, python-format
msgid "Domain is disabled: %s"
msgstr "å·²åœç”¨ç¶²åŸŸï¼š%s"
-#: keystone/auth/controllers.py:84 keystone/auth/plugins/password.py:45
+#: keystone/auth/controllers.py:83 keystone/auth/plugins/password.py:44
#, python-format
msgid "User is disabled: %s"
msgstr "å·²åœç”¨ä½¿ç”¨è€…:%s"
-#: keystone/auth/controllers.py:265
+#: keystone/auth/controllers.py:262
msgid "Scoping to both domain and project is not allowed"
msgstr "ä¸å®¹è¨±å°‡ç¯„åœåŒæ™‚設定為網域åŠå°ˆæ¡ˆ"
-#: keystone/auth/controllers.py:268
+#: keystone/auth/controllers.py:265
msgid "Scoping to both domain and trust is not allowed"
msgstr "ä¸å®¹è¨±å°‡ç¯„åœåŒæ™‚設定為網域åŠä¿¡ä»»"
-#: keystone/auth/controllers.py:271
+#: keystone/auth/controllers.py:268
msgid "Scoping to both project and trust is not allowed"
msgstr "ä¸å®¹è¨±å°‡ç¯„åœåŒæ™‚設定為專案åŠä¿¡ä»»"
-#: keystone/auth/controllers.py:333
-#, python-format
-msgid "Unable to lookup user %s"
-msgstr "無法查閱使用者 %s"
-
-#: keystone/auth/controllers.py:363
+#: keystone/auth/controllers.py:353
msgid "User not found"
msgstr "找ä¸åˆ°ä½¿ç”¨è€…"
-#: keystone/auth/token_factory.py:81
-msgid "User have no access to project"
-msgstr "使用者無法存å–專案"
-
-#: keystone/auth/token_factory.py:96
-msgid "User have no access to domain"
-msgstr "使用者無法存å–網域"
-
-#: keystone/auth/token_factory.py:314 keystone/token/controllers.py:121
-msgid "Unable to sign token."
-msgstr "無法簽署記號。"
+#: keystone/auth/plugins/external.py:36 keystone/auth/plugins/external.py:66
+msgid "No authenticated user"
+msgstr ""
-#: keystone/auth/token_factory.py:317 keystone/token/controllers.py:124
+#: keystone/auth/plugins/external.py:49 keystone/auth/plugins/external.py:86
#, python-format
-msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
-msgstr "token_format 的值無效:%s。接å—的值為 PKI 或 UUID。"
+msgid "Unable to lookup user %s"
+msgstr "無法查閱使用者 %s"
+
+#: keystone/auth/plugins/password.py:112
+msgid "Invalid username or password"
+msgstr ""
#: keystone/catalog/core.py:38
#, python-format
@@ -120,18 +282,18 @@ msgstr "端點 %s çš„æ ¼å¼ä¸æ­£ç¢º - æ ¼å¼ä¸å®Œæ•´ï¼ˆéºæ¼äº†é¡žåž‹é€šçŸ¥ç¬
msgid "Unable to open template file %s"
msgstr "無法開啟範本檔 %s"
-#: keystone/common/cms.py:42
+#: keystone/common/cms.py:26
#, python-format
msgid "Verify error: %s"
msgstr "驗證發生錯誤:%s"
-#: keystone/common/cms.py:134
+#: keystone/common/cms.py:118
msgid ""
"Signing error: Unable to load certificate - ensure you've configured PKI "
"with 'keystone-manage pki_setup'"
msgstr "簽署發生錯誤:無法載入憑證 - 請確ä¿å·²ä½¿ç”¨ 'keystone-manage pki_setup' 來é…ç½® PKI"
-#: keystone/common/cms.py:138
+#: keystone/common/cms.py:122
#, python-format
msgid "Signing error: %s"
msgstr "簽署發生錯誤:%s"
@@ -150,31 +312,31 @@ msgstr "無效的 Syslog 機能"
msgid "RBAC: Authorizing %(action)s(%(kwargs)s)"
msgstr ""
-#: keystone/common/controller.py:26
+#: keystone/common/controller.py:25
msgid "RBAC: Invalid token"
msgstr "RBAC:無效的記號"
-#: keystone/common/controller.py:36 keystone/common/controller.py:57
+#: keystone/common/controller.py:39 keystone/common/controller.py:60
msgid "RBAC: Invalid user"
msgstr "RBAC:無效的使用者"
-#: keystone/common/controller.py:42
+#: keystone/common/controller.py:45
msgid "RBAC: Proceeding without project"
msgstr "RBAC:在沒有專案的情æ³ä¸‹ç¹¼çºŒä½œæ¥­"
-#: keystone/common/controller.py:62
+#: keystone/common/controller.py:65
msgid "RBAC: Proceeding without tenant"
msgstr "RBAC:在沒有 Tenant 的情æ³ä¸‹ç¹¼çºŒä½œæ¥­"
-#: keystone/common/controller.py:92 keystone/common/controller.py:144
+#: keystone/common/controller.py:95 keystone/common/controller.py:146
msgid "RBAC: Bypassing authorization"
msgstr "RBAC:正在略éŽæŽˆæ¬Š"
-#: keystone/common/controller.py:101 keystone/common/controller.py:142
+#: keystone/common/controller.py:104 keystone/common/controller.py:144
msgid "RBAC: Authorization granted"
msgstr "RBAC:已授與權é™"
-#: keystone/common/controller.py:131
+#: keystone/common/controller.py:134
#, python-format
msgid "RBAC: Adding query filter params (%s)"
msgstr "RBAC:正在新增查詢éŽæ¿¾å™¨åƒæ•¸ (%s)"
@@ -183,33 +345,69 @@ msgstr "RBAC:正在新增查詢éŽæ¿¾å™¨åƒæ•¸ (%s)"
msgid "Invalid token in normalize_domain_id"
msgstr "normalize_domain_id 中的記號無效"
-#: keystone/common/utils.py:232
+#: keystone/common/utils.py:233
msgid ""
"Error setting up the debug environment. Verify that the option --debug-"
"url has the format <host>:<port> and that a debugger processes is "
"listening on that port."
msgstr ""
-#: keystone/common/wsgi.py:162
+#: keystone/common/wsgi.py:95
+msgid "No bind information present in token"
+msgstr ""
+
+#: keystone/common/wsgi.py:99
+#, python-format
+msgid "Named bind mode %s not in bind information"
+msgstr ""
+
+#: keystone/common/wsgi.py:105
+msgid "Kerberos credentials required and not present"
+msgstr ""
+
+#: keystone/common/wsgi.py:109
+msgid "Kerberos credentials do not match those in bind"
+msgstr ""
+
+#: keystone/common/wsgi.py:112
+msgid "Kerberos bind authentication successful"
+msgstr ""
+
+#: keystone/common/wsgi.py:115
+#, python-format
+msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:119
+#, python-format
+msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}"
+msgstr ""
+
+#: keystone/common/wsgi.py:211
#, python-format
msgid "arg_dict: %s"
msgstr "arg_dict:%s"
-#: keystone/common/wsgi.py:186
+#: keystone/common/wsgi.py:243
#, fuzzy, python-format
msgid "Authorization failed. %(exception)s from %(remote_addr)s"
msgstr "授權失敗。%s(自 %s)"
-#: keystone/common/wsgi.py:429
+#: keystone/common/wsgi.py:487
msgid "The resource could not be found."
msgstr "找ä¸åˆ°è³‡æºã€‚"
-#: keystone/common/wsgi_server.py:72
+#: keystone/common/environment/__init__.py:37
+#, python-format
+msgid "Environment configured as: %s"
+msgstr ""
+
+#: keystone/common/environment/eventlet_server.py:51
#, python-format
msgid "Starting %(arg0)s on %(host)s:%(port)s"
msgstr "正在 %(host)s:%(port)s 上啟動 %(arg0)s"
-#: keystone/common/wsgi_server.py:132
+#: keystone/common/environment/eventlet_server.py:113
msgid "Server error"
msgstr "伺æœå™¨éŒ¯èª¤"
@@ -242,13 +440,13 @@ msgid ""
"\"%(attr_map)s\" must use one of %(keys)s."
msgstr ""
-#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:596
-#: keystone/identity/backends/kvs.py:624
+#: keystone/common/ldap/core.py:279 keystone/identity/backends/kvs.py:177
+#: keystone/identity/backends/kvs.py:205
#, python-format
msgid "Duplicate name, %s."
msgstr "é‡è¤‡çš„å稱,%s。"
-#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:589
+#: keystone/common/ldap/core.py:289 keystone/identity/backends/kvs.py:170
#, python-format
msgid "Duplicate ID, %s."
msgstr "é‡è¤‡çš„ ID,%s。"
@@ -436,12 +634,16 @@ msgstr "FakeLdap æœå°‹å¤±æ•—:找ä¸åˆ° SCOPE_BASE çš„ DN"
msgid "Search scope %s not implemented."
msgstr "未實作æœå°‹ç¯„åœ %s。"
-#: keystone/common/sql/core.py:205
+#: keystone/common/sql/core.py:119
+msgid "Global engine callback raised."
+msgstr ""
+
+#: keystone/common/sql/core.py:233
#, python-format
msgid "Got mysql server has gone away: %s"
msgstr "å·²å–å¾— mysql 伺æœå™¨å·²æ–·ç·šçš„訊æ¯ï¼š%s"
-#: keystone/common/sql/legacy.py:180
+#: keystone/common/sql/legacy.py:188
#, python-format
msgid "Cannot migrate EC2 credential: %s"
msgstr "無法移轉 EC2 èªè­‰ï¼š%s"
@@ -450,76 +652,68 @@ msgstr "無法移轉 EC2 èªè­‰ï¼š%s"
msgid "version should be an integer"
msgstr "版本應該是整數"
-#: keystone/common/sql/nova.py:62
+#: keystone/common/sql/nova.py:65
#, python-format
msgid "Create tenant %s"
msgstr "建立 Tenant %s"
-#: keystone/common/sql/nova.py:79
+#: keystone/common/sql/nova.py:82
#, python-format
msgid "Create user %s"
msgstr "建立使用者 %s"
-#: keystone/common/sql/nova.py:88
+#: keystone/common/sql/nova.py:91
#, fuzzy, python-format
msgid "Add user %(user_id)s to tenant %(tenant_id)s"
msgstr "將使用者 %s 新增至 Tenant %s"
-#: keystone/common/sql/nova.py:97
+#: keystone/common/sql/nova.py:100
#, python-format
msgid "Ignoring existing role %s"
msgstr "正在忽略ç¾æœ‰è§’色 %s"
-#: keystone/common/sql/nova.py:104
+#: keystone/common/sql/nova.py:107
#, python-format
msgid "Create role %s"
msgstr "建立角色 %s"
-#: keystone/common/sql/nova.py:114
+#: keystone/common/sql/nova.py:117
#, fuzzy, python-format
msgid "Assign role %(role_id)s to user %(user_id)s on tenant %(tenant_id)s"
msgstr "將角色 %s 指派給使用者 %s(在 Tenant %s 上)"
-#: keystone/common/sql/nova.py:133
+#: keystone/common/sql/nova.py:136
#, fuzzy, python-format
msgid "Creating ec2 cred for user %(user_id)s and tenant %(tenant_id)s"
msgstr "正在給使用者 %s åŠ Tenant %s 建立 EC2 Cred"
-#: keystone/identity/backends/kvs.py:250 keystone/identity/backends/kvs.py:259
+#: keystone/identity/controllers.py:952
+#, python-format
+msgid ""
+"Group %(group)s not found for role-assignment - %(target)s with Role: "
+"%(role)s"
+msgstr ""
+
+#: keystone/identity/backends/kvs.py:126 keystone/identity/backends/kvs.py:135
msgid "User not found in group"
msgstr "在群組中找ä¸åˆ°ä½¿ç”¨è€…"
-#: keystone/identity/backends/sql.py:425
-#, python-format
-msgid "Cannot remove role that has not been granted, %s"
-msgstr "無法移除尚未授權的角色,%s"
-
-#: keystone/identity/backends/ldap/core.py:82
+#: keystone/identity/backends/ldap.py:189
#, python-format
-msgid "Expected dict or list: %s"
+msgid ""
+"Group member '%(user_dn)s' not found in '%(group_id)s'. The user should "
+"be removed from the group. The user will be ignored."
msgstr ""
-#: keystone/identity/backends/ldap/core.py:681
-#, python-format
-msgid "Role %s not found"
-msgstr "找ä¸åˆ°è§’色 %s"
-
-#: keystone/identity/backends/ldap/core.py:898
+#: keystone/identity/backends/ldap.py:334
msgid "Changing Name not supported by LDAP"
msgstr "LDAP ä¸æ”¯æ´è®Šæ›´å稱"
-#: keystone/identity/backends/ldap/core.py:911
+#: keystone/identity/backends/ldap.py:347
#, fuzzy, python-format
msgid "User %(user_id)s is already a member of group %(group_id)s"
msgstr "使用者 %s 已是群組 %s çš„æˆå“¡"
-#: keystone/identity/backends/ldap/core.py:954
-#, python-format
-msgid ""
-"Group member '%(user_dn)s' not found in '%(group_dn)s'. The user should "
-"be removed from the group. The user will be ignored."
-msgstr ""
-
#: keystone/openstack/common/policy.py:394
#, python-format
msgid "Failed to understand rule %(rule)s"
@@ -535,22 +729,57 @@ msgstr "類型為 %s 的相符項沒有處ç†ç¨‹å¼"
msgid "Failed to understand rule %(rule)r"
msgstr "無法ç†è§£è¦å‰‡ %(rule)r"
+#: keystone/openstack/common/crypto/utils.py:29
+msgid "An unknown error occurred in crypto utils."
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:36
+#, python-format
+msgid "Block size of %(given)d is too big, max = %(maximum)d"
+msgstr ""
+
+#: keystone/openstack/common/crypto/utils.py:45
+#, python-format
+msgid "Length of %(given)d is too long, max = %(maximum)d"
+msgstr ""
+
#: keystone/policy/backends/rules.py:93
#, python-format
msgid "enforce %(action)s: %(credentials)s"
msgstr ""
-#: keystone/token/controllers.py:465 keystone/token/controllers.py:468
+#: keystone/token/controllers.py:378
+#, python-format
+msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
+msgstr ""
+
+#: keystone/token/controllers.py:395 keystone/token/controllers.py:398
msgid "Token does not belong to specified tenant."
msgstr "記號ä¸å±¬æ–¼æ‰€æŒ‡å®šçš„ Tenant。"
-#: keystone/token/controllers.py:475
-msgid "Non-default domain is not supported"
-msgstr "ä¸æ”¯æ´éžé è¨­ç¶²åŸŸ"
+#: keystone/token/provider.py:76
+msgid ""
+"keystone.conf [signing] token_format (deprecated) conflicts with "
+"keystone.conf [token] provider"
+msgstr ""
-#: keystone/token/controllers.py:483
-msgid "Domain scoped token is not supported"
-msgstr "ä¸æ”¯æ´ç¶²åŸŸç¯„åœçš„記號"
+#: keystone/token/provider.py:84
+msgid ""
+"keystone.conf [signing] token_format is deprecated in favor of "
+"keystone.conf [token] provider"
+msgstr ""
+
+#: keystone/token/provider.py:94
+msgid ""
+"Unrecognized keystone.conf [signing] token_format: expected either 'UUID'"
+" or 'PKI'"
+msgstr ""
+
+#: keystone/token/backends/kvs.py:37
+msgid ""
+"kvs token backend is DEPRECATED. Use keystone.token.backends.sql or "
+"keystone.token.backend.memcache instead."
+msgstr ""
#: keystone/token/backends/memcache.py:144
#, python-format
@@ -574,3 +803,54 @@ msgstr ""
msgid "Unable to add token to revocation list."
msgstr "無法將記號新增至撤銷清冊。"
+#: keystone/token/providers/pki.py:43
+msgid "Unable to sign token."
+msgstr "無法簽署記號。"
+
+#: keystone/token/providers/uuid.py:193
+msgid "Trustor is disabled."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:238
+msgid "Trustee has no delegated roles."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:247
+#, python-format
+msgid "User %(user_id)s has no access to project %(project_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:252
+#, python-format
+msgid "User %(user_id)s has no access to domain %(domain_id)s"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:303
+msgid "User is not a trustee."
+msgstr ""
+
+#: keystone/token/providers/uuid.py:457
+msgid "Non-default domain is not supported"
+msgstr "ä¸æ”¯æ´éžé è¨­ç¶²åŸŸ"
+
+#: keystone/token/providers/uuid.py:465
+msgid "Domain scoped token is not supported"
+msgstr "ä¸æ”¯æ´ç¶²åŸŸç¯„åœçš„記號"
+
+#: keystone/token/providers/uuid.py:528
+msgid "Failed to validate token"
+msgstr ""
+
+#: keystone/token/providers/uuid.py:566 keystone/token/providers/uuid.py:576
+msgid "Failed to verify token"
+msgstr ""
+
+#~ msgid "User have no access to project"
+#~ msgstr "使用者無法存å–專案"
+
+#~ msgid "User have no access to domain"
+#~ msgstr "使用者無法存å–網域"
+
+#~ msgid "Invalid value for token_format: %s. Allowed values are PKI or UUID."
+#~ msgstr "token_format 的值無效:%s。接å—的值為 PKI 或 UUID。"
+
diff --git a/keystone/openstack/common/crypto/__init__.py b/keystone/openstack/common/crypto/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/keystone/openstack/common/crypto/__init__.py
diff --git a/keystone/openstack/common/crypto/utils.py b/keystone/openstack/common/crypto/utils.py
new file mode 100644
index 00000000..ef178cab
--- /dev/null
+++ b/keystone/openstack/common/crypto/utils.py
@@ -0,0 +1,179 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 Red Hat, Inc.
+#
+# 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 base64
+
+from Crypto.Hash import HMAC
+from Crypto import Random
+
+from keystone.openstack.common.gettextutils import _
+from keystone.openstack.common.importutils import import_module
+
+
+class CryptoutilsException(Exception):
+ """Generic Exception for Crypto utilities."""
+
+ message = _("An unknown error occurred in crypto utils.")
+
+
+class CipherBlockLengthTooBig(CryptoutilsException):
+ """The block size is too big."""
+
+ def __init__(self, requested, permitted):
+ msg = _("Block size of %(given)d is too big, max = %(maximum)d")
+ message = msg % {'given': requested, 'maximum': permitted}
+ super(CryptoutilsException, self).__init__(message)
+
+
+class HKDFOutputLengthTooLong(CryptoutilsException):
+ """The amount of Key Material asked is too much."""
+
+ def __init__(self, requested, permitted):
+ msg = _("Length of %(given)d is too long, max = %(maximum)d")
+ message = msg % {'given': requested, 'maximum': permitted}
+ super(CryptoutilsException, self).__init__(message)
+
+
+class HKDF(object):
+ """An HMAC-based Key Derivation Function implementation (RFC5869)
+
+ This class creates an object that allows to use HKDF to derive keys.
+ """
+
+ def __init__(self, hashtype='SHA256'):
+ self.hashfn = import_module('Crypto.Hash.' + hashtype)
+ self.max_okm_length = 255 * self.hashfn.digest_size
+
+ def extract(self, ikm, salt=None):
+ """An extract function that can be used to derive a robust key given
+ weak Input Key Material (IKM) which could be a password.
+ Returns a pseudorandom key (of HashLen octets)
+
+ :param ikm: input keying material (ex a password)
+ :param salt: optional salt value (a non-secret random value)
+ """
+ if salt is None:
+ salt = '\x00' * self.hashfn.digest_size
+
+ return HMAC.new(salt, ikm, self.hashfn).digest()
+
+ def expand(self, prk, info, length):
+ """An expand function that will return arbitrary length output that can
+ be used as keys.
+ Returns a buffer usable as key material.
+
+ :param prk: a pseudorandom key of at least HashLen octets
+ :param info: optional string (can be a zero-length string)
+ :param length: length of output keying material (<= 255 * HashLen)
+ """
+ if length > self.max_okm_length:
+ raise HKDFOutputLengthTooLong(length, self.max_okm_length)
+
+ N = (length + self.hashfn.digest_size - 1) / self.hashfn.digest_size
+
+ okm = ""
+ tmp = ""
+ for block in range(1, N + 1):
+ tmp = HMAC.new(prk, tmp + info + chr(block), self.hashfn).digest()
+ okm += tmp
+
+ return okm[:length]
+
+
+MAX_CB_SIZE = 256
+
+
+class SymmetricCrypto(object):
+ """Symmetric Key Crypto object.
+
+ This class creates a Symmetric Key Crypto object that can be used
+ to encrypt, decrypt, or sign arbitrary data.
+
+ :param enctype: Encryption Cipher name (default: AES)
+ :param hashtype: Hash/HMAC type name (default: SHA256)
+ """
+
+ def __init__(self, enctype='AES', hashtype='SHA256'):
+ self.cipher = import_module('Crypto.Cipher.' + enctype)
+ self.hashfn = import_module('Crypto.Hash.' + hashtype)
+
+ def new_key(self, size):
+ return Random.new().read(size)
+
+ def encrypt(self, key, msg, b64encode=True):
+ """Encrypt the provided msg and returns the cyphertext optionally
+ base64 encoded.
+
+ Uses AES-128-CBC with a Random IV by default.
+
+ The plaintext is padded to reach blocksize length.
+ The last byte of the block is the length of the padding.
+ The length of the padding does not include the length byte itself.
+
+ :param key: The Encryption key.
+ :param msg: the plain text.
+
+ :returns encblock: a block of encrypted data.
+ """
+ iv = Random.new().read(self.cipher.block_size)
+ cipher = self.cipher.new(key, self.cipher.MODE_CBC, iv)
+
+ # CBC mode requires a fixed block size. Append padding and length of
+ # padding.
+ if self.cipher.block_size > MAX_CB_SIZE:
+ raise CipherBlockLengthTooBig(self.cipher.block_size, MAX_CB_SIZE)
+ r = len(msg) % self.cipher.block_size
+ padlen = self.cipher.block_size - r - 1
+ msg += '\x00' * padlen
+ msg += chr(padlen)
+
+ enc = iv + cipher.encrypt(msg)
+ if b64encode:
+ enc = base64.b64encode(enc)
+ return enc
+
+ def decrypt(self, key, msg, b64decode=True):
+ """Decrypts the provided ciphertext, optionally base 64 encoded, and
+ returns the plaintext message, after padding is removed.
+
+ Uses AES-128-CBC with an IV by default.
+
+ :param key: The Encryption key.
+ :param msg: the ciphetext, the first block is the IV
+ """
+ if b64decode:
+ msg = base64.b64decode(msg)
+ iv = msg[:self.cipher.block_size]
+ cipher = self.cipher.new(key, self.cipher.MODE_CBC, iv)
+
+ padded = cipher.decrypt(msg[self.cipher.block_size:])
+ l = ord(padded[-1]) + 1
+ plain = padded[:-l]
+ return plain
+
+ def sign(self, key, msg, b64encode=True):
+ """Signs a message string and returns a base64 encoded signature.
+
+ Uses HMAC-SHA-256 by default.
+
+ :param key: The Signing key.
+ :param msg: the message to sign.
+ """
+ h = HMAC.new(key, msg, self.hashfn)
+ out = h.digest()
+ if b64encode:
+ out = base64.b64encode(out)
+ return out
diff --git a/keystone/service.py b/keystone/service.py
index 406004d6..ce64aba8 100644
--- a/keystone/service.py
+++ b/keystone/service.py
@@ -16,8 +16,10 @@
import routes
+from keystone import assignment
from keystone import auth
from keystone import catalog
+from keystone.common import dependency
from keystone.common import logging
from keystone.common import wsgi
from keystone import config
@@ -34,14 +36,24 @@ from keystone import trust
CONF = config.CONF
LOG = logging.getLogger(__name__)
+
+# Ensure that the identity driver is created before the assignment manager.
+# The default assignment driver is determined by the identity driver, so the
+# identity driver must be available to the assignment manager.
+_IDENTITY_API = identity.Manager()
+
DRIVERS = dict(
+ assignment_api=assignment.Manager(),
catalog_api=catalog.Manager(),
credentials_api=credential.Manager(),
ec2_api=ec2.Manager(),
- identity_api=identity.Manager(),
+ identity_api=_IDENTITY_API,
policy_api=policy.Manager(),
token_api=token.Manager(),
- trust_api=trust.Manager())
+ trust_api=trust.Manager(),
+ token_provider_api=token.provider.Manager())
+
+dependency.resolve_future_dependencies()
@logging.fail_gracefully
diff --git a/keystone/test.py b/keystone/test.py
index e68676ca..9118b2ea 100644
--- a/keystone/test.py
+++ b/keystone/test.py
@@ -17,6 +17,7 @@
import datetime
import errno
import os
+import shutil
import socket
import StringIO
import sys
@@ -35,18 +36,23 @@ gettext.install('keystone', unicode=1)
from keystone.common import environment
environment.use_eventlet()
+from keystone import assignment
from keystone import catalog
+from keystone.common import dependency
from keystone.common import kvs
from keystone.common import logging
+from keystone.common import sql
from keystone.common import utils
from keystone.common import wsgi
from keystone import config
+from keystone.contrib import ec2
from keystone import credential
from keystone import exception
from keystone import identity
from keystone.openstack.common import timeutils
from keystone import policy
from keystone import token
+from keystone.token import provider as token_provider
from keystone import trust
@@ -55,6 +61,8 @@ ROOTDIR = os.path.dirname(os.path.abspath(os.curdir))
VENDOR = os.path.join(ROOTDIR, 'vendor')
TESTSDIR = os.path.join(ROOTDIR, 'tests')
ETCDIR = os.path.join(ROOTDIR, 'etc')
+TMPDIR = os.path.join(TESTSDIR, 'tmp')
+
CONF = config.CONF
cd = os.chdir
@@ -75,6 +83,10 @@ def testsdir(*p):
return os.path.join(TESTSDIR, *p)
+def tmpdir(*p):
+ return os.path.join(TMPDIR, *p)
+
+
def checkout_vendor(repo, rev):
# TODO(termie): this function is a good target for some optimizations :PERF
name = repo.split('/')[-1]
@@ -107,6 +119,26 @@ def checkout_vendor(repo, rev):
return revdir
+def setup_test_database():
+ db = tmpdir('test.db')
+ pristine = tmpdir('test.db.pristine')
+
+ try:
+ if os.path.exists(db):
+ os.unlink(db)
+ if not os.path.exists(pristine):
+ sql.migration.db_sync()
+ shutil.copyfile(db, pristine)
+ else:
+ shutil.copyfile(pristine, db)
+ except Exception:
+ pass
+
+
+def teardown_test_database():
+ sql.core.set_global_engine(None)
+
+
class TestClient(object):
def __init__(self, app=None, token=None):
self.app = app
@@ -210,6 +242,11 @@ class TestCase(NoModule, unittest.TestCase):
for path in self._paths:
if path in sys.path:
sys.path.remove(path)
+
+ # Clear the registry of providers so that providers from previous
+ # tests aren't used.
+ dependency.reset()
+
kvs.INMEMDB.clear()
CONF.reset()
@@ -223,10 +260,28 @@ class TestCase(NoModule, unittest.TestCase):
def load_backends(self):
"""Initializes each manager and assigns them to an attribute."""
- for manager in [catalog, credential, identity, policy, token, trust]:
- manager_name = '%s_api' % manager.__name__.split('.')[-1]
+
+ # TODO(blk-u): Shouldn't need to clear the registry here, but some
+ # tests call load_backends multiple times. These should be fixed to
+ # only call load_backends once.
+ dependency.reset()
+
+ # NOTE(blk-u): identity must be before assignment to ensure that the
+ # identity driver is available to the assignment manager because the
+ # assignment manager gets the default assignment driver from the
+ # identity driver.
+ for manager in [identity, assignment, catalog, credential, ec2, policy,
+ token, token_provider, trust]:
+ # manager.__name__ is like keystone.xxx[.yyy],
+ # converted to xxx[_yyy]
+ manager_name = ('%s_api' %
+ manager.__name__.replace('keystone.', '').
+ replace('.', '_'))
+
setattr(self, manager_name, manager.Manager())
+ dependency.resolve_future_dependencies()
+
def load_fixtures(self, fixtures):
"""Hacky basic and naive fixture loading based on a python module.
@@ -276,19 +331,6 @@ class TestCase(NoModule, unittest.TestCase):
pass
setattr(self, 'user_%s' % user['id'], user_copy)
- for metadata in fixtures.METADATA:
- metadata_ref = metadata.copy()
- # TODO(termie): these will probably end up in the model anyway,
- # so this may be futile
- del metadata_ref['user_id']
- del metadata_ref['tenant_id']
- rv = self.identity_api.create_metadata(metadata['user_id'],
- metadata['tenant_id'],
- metadata_ref)
- setattr(self,
- 'metadata_%s%s' % (metadata['user_id'],
- metadata['tenant_id']), rv)
-
def _paste_config(self, config):
if not config.startswith('config:'):
test_path = os.path.join(TESTSDIR, config)
diff --git a/keystone/token/__init__.py b/keystone/token/__init__.py
index 889cd39a..ffd9bc44 100644
--- a/keystone/token/__init__.py
+++ b/keystone/token/__init__.py
@@ -17,4 +17,5 @@
from keystone.token import controllers
from keystone.token.core import *
+from keystone.token import provider
from keystone.token import routers
diff --git a/keystone/token/backends/kvs.py b/keystone/token/backends/kvs.py
index c16dd61b..c3c3e769 100644
--- a/keystone/token/backends/kvs.py
+++ b/keystone/token/backends/kvs.py
@@ -17,16 +17,29 @@
import copy
from keystone.common import kvs
+from keystone.common import logging
from keystone import exception
from keystone.openstack.common import timeutils
from keystone import token
+LOG = logging.getLogger(__name__)
+
class Token(kvs.Base, token.Driver):
+ """kvs backend for tokens is deprecated.
+
+ Deprecated in Havana and will be removed in Icehouse, as this backend
+ is not production grade.
+ """
+
+ def __init__(self, *args, **kw):
+ super(Token, self).__init__(*args, **kw)
+ LOG.warn(_("kvs token backend is DEPRECATED. Use "
+ "keystone.token.backends.sql or "
+ "keystone.token.backend.memcache instead."))
# Public interface
def get_token(self, token_id):
- token_id = token.unique_id(token_id)
try:
ref = self.db.get('token-%s' % token_id)
except exception.NotFound:
@@ -41,7 +54,6 @@ class Token(kvs.Base, token.Driver):
raise exception.TokenNotFound(token_id=token_id)
def create_token(self, token_id, data):
- token_id = token.unique_id(token_id)
data_copy = copy.deepcopy(data)
data_copy['id'] = token_id
if not data_copy.get('expires'):
@@ -52,7 +64,6 @@ class Token(kvs.Base, token.Driver):
return copy.deepcopy(data_copy)
def delete_token(self, token_id):
- token_id = token.unique_id(token_id)
try:
token_ref = self.get_token(token_id)
self.db.delete('token-%s' % token_id)
diff --git a/keystone/token/backends/memcache.py b/keystone/token/backends/memcache.py
index e9d8482f..06e89d60 100644
--- a/keystone/token/backends/memcache.py
+++ b/keystone/token/backends/memcache.py
@@ -65,7 +65,7 @@ class Token(token.Driver):
def get_token(self, token_id):
if token_id is None:
raise exception.TokenNotFound(token_id='')
- ptk = self._prefix_token_id(token.unique_id(token_id))
+ ptk = self._prefix_token_id(token_id)
token_ref = self.client.get(ptk)
if token_ref is None:
raise exception.TokenNotFound(token_id=token_id)
@@ -74,7 +74,7 @@ class Token(token.Driver):
def create_token(self, token_id, data):
data_copy = copy.deepcopy(data)
- ptk = self._prefix_token_id(token.unique_id(token_id))
+ ptk = self._prefix_token_id(token_id)
if not data_copy.get('expires'):
data_copy['expires'] = token.default_expire_time()
if not data_copy.get('user_id'):
@@ -118,7 +118,7 @@ class Token(token.Driver):
if record is not None:
token_list = jsonutils.loads('[%s]' % record)
for token_i in token_list:
- ptk = self._prefix_token_id(token.unique_id(token_i))
+ ptk = self._prefix_token_id(token_i)
token_ref = self.client.get(ptk)
if not token_ref:
# skip tokens that do not exist in memcache
@@ -174,8 +174,8 @@ class Token(token.Driver):
def delete_token(self, token_id):
# Test for existence
- data = self.get_token(token.unique_id(token_id))
- ptk = self._prefix_token_id(token.unique_id(token_id))
+ data = self.get_token(token_id)
+ ptk = self._prefix_token_id(token_id)
result = self.client.delete(ptk)
self._add_to_revocation_list(data)
return result
@@ -186,7 +186,7 @@ class Token(token.Driver):
user_record = self.client.get(user_key) or ""
token_list = jsonutils.loads('[%s]' % user_record)
for token_id in token_list:
- ptk = self._prefix_token_id(token.unique_id(token_id))
+ ptk = self._prefix_token_id(token_id)
token_ref = self.client.get(ptk)
if token_ref:
if tenant_id is not None:
diff --git a/keystone/token/backends/sql.py b/keystone/token/backends/sql.py
index 57dbf410..0e8a916d 100644
--- a/keystone/token/backends/sql.py
+++ b/keystone/token/backends/sql.py
@@ -41,7 +41,7 @@ class Token(sql.Base, token.Driver):
if token_id is None:
raise exception.TokenNotFound(token_id=token_id)
session = self.get_session()
- token_ref = session.query(TokenModel).get(token.unique_id(token_id))
+ token_ref = session.query(TokenModel).get(token_id)
now = datetime.datetime.utcnow()
if not token_ref or not token_ref.valid:
raise exception.TokenNotFound(token_id=token_id)
@@ -59,7 +59,6 @@ class Token(sql.Base, token.Driver):
data_copy['user_id'] = data_copy['user']['id']
token_ref = TokenModel.from_dict(data_copy)
- token_ref.id = token.unique_id(token_id)
token_ref.valid = True
session = self.get_session()
with session.begin():
@@ -69,9 +68,8 @@ class Token(sql.Base, token.Driver):
def delete_token(self, token_id):
session = self.get_session()
- key = token.unique_id(token_id)
with session.begin():
- token_ref = session.query(TokenModel).get(key)
+ token_ref = session.query(TokenModel).get(token_id)
if not token_ref or not token_ref.valid:
raise exception.TokenNotFound(token_id=token_id)
token_ref.valid = False
diff --git a/keystone/token/controllers.py b/keystone/token/controllers.py
index 34700106..9ebc29fe 100644
--- a/keystone/token/controllers.py
+++ b/keystone/token/controllers.py
@@ -1,17 +1,17 @@
import json
-import sys
-import uuid
from keystone.common import cms
from keystone.common import controller
from keystone.common import dependency
-from keystone.common import environment
from keystone.common import logging
from keystone.common import utils
+from keystone.common import wsgi
from keystone import config
from keystone import exception
from keystone.openstack.common import timeutils
from keystone.token import core
+from keystone.token import provider as token_provider
+
CONF = config.CONF
LOG = logging.getLogger(__name__)
@@ -23,7 +23,7 @@ class ExternalAuthNotApplicable(Exception):
pass
-@dependency.requires('catalog_api', 'trust_api', 'token_api')
+@dependency.requires('token_provider_api')
class Auth(controller.V2Controller):
def ca_cert(self, context, auth=None):
ca_file = open(CONF.signing.ca_certs, 'r')
@@ -79,9 +79,8 @@ class Auth(controller.V2Controller):
auth_info = self._authenticate_local(
context, auth)
- user_ref, tenant_ref, metadata_ref, expiry = auth_info
+ user_ref, tenant_ref, metadata_ref, expiry, bind = auth_info
core.validate_auth_info(self, user_ref, tenant_ref)
- trust_id = metadata_ref.get('trust_id')
user_ref = self._filter_domain_id(user_ref)
if tenant_ref:
tenant_ref = self._filter_domain_id(tenant_ref)
@@ -92,59 +91,24 @@ class Auth(controller.V2Controller):
if tenant_ref:
catalog_ref = self.catalog_api.get_catalog(
- user_id=user_ref['id'],
- tenant_id=tenant_ref['id'],
- metadata=metadata_ref)
+ user_ref['id'], tenant_ref['id'], metadata_ref)
else:
catalog_ref = {}
auth_token_data['id'] = 'placeholder'
+ if bind:
+ auth_token_data['bind'] = bind
roles_ref = []
for role_id in metadata_ref.get('roles', []):
role_ref = self.identity_api.get_role(role_id)
roles_ref.append(dict(name=role_ref['name']))
- token_data = Auth.format_token(auth_token_data, roles_ref)
-
- service_catalog = Auth.format_catalog(catalog_ref)
- token_data['access']['serviceCatalog'] = service_catalog
-
- if CONF.signing.token_format == 'UUID':
- token_id = uuid.uuid4().hex
- elif CONF.signing.token_format == 'PKI':
- try:
- token_id = cms.cms_sign_token(json.dumps(token_data),
- CONF.signing.certfile,
- CONF.signing.keyfile)
- except environment.subprocess.CalledProcessError:
- raise exception.UnexpectedError(_(
- 'Unable to sign token.'))
- else:
- raise exception.UnexpectedError(_(
- 'Invalid value for token_format: %s.'
- ' Allowed values are PKI or UUID.') %
- CONF.signing.token_format)
- try:
- self.token_api.create_token(
- token_id, dict(key=token_id,
- id=token_id,
- expires=auth_token_data['expires'],
- user=user_ref,
- tenant=tenant_ref,
- metadata=metadata_ref,
- trust_id=trust_id))
- except Exception:
- exc_info = sys.exc_info()
- # an identical token may have been created already.
- # if so, return the token_data as it is also identical
- try:
- self.token_api.get_token(token_id)
- except exception.TokenNotFound:
- raise exc_info[0], exc_info[1], exc_info[2]
-
- token_data['access']['token']['id'] = token_id
-
+ (token_id, token_data) = self.token_provider_api.issue_token(
+ version=token_provider.V2,
+ token_ref=auth_token_data,
+ roles_ref=roles_ref,
+ catalog_ref=catalog_ref)
return token_data
def _authenticate_token(self, context, auth):
@@ -170,6 +134,8 @@ class Auth(controller.V2Controller):
except exception.NotFound as e:
raise exception.Unauthorized(e)
+ wsgi.validate_token_bind(context, old_token_ref)
+
#A trust token cannot be used to get another token
if 'trust' in old_token_ref:
raise exception.Forbidden()
@@ -207,17 +173,10 @@ class Auth(controller.V2Controller):
else:
current_user_ref = self.identity_api.get_user(user_id)
+ metadata_ref = {}
tenant_id = self._get_project_id_from_auth(auth)
-
- tenant_ref = self._get_project_ref(user_id, tenant_id)
- metadata_ref = self._get_metadata_ref(user_id, tenant_id)
-
- # TODO(henry-nash): If no tenant was specified, instead check for a
- # domain and find any related user/group roles
-
- self._append_roles(metadata_ref,
- self._get_group_metadata_ref(
- context, user_id, tenant_id))
+ tenant_ref, metadata_ref['roles'] = self._get_project_roles_and_ref(
+ user_id, tenant_id)
expiry = old_token_ref['expires']
if CONF.trust.enabled and 'trust_id' in auth:
@@ -238,7 +197,9 @@ class Auth(controller.V2Controller):
metadata_ref['trustee_user_id'] = trust_ref['trustee_user_id']
metadata_ref['trust_id'] = trust_id
- return (current_user_ref, tenant_ref, metadata_ref, expiry)
+ bind = old_token_ref.get('bind', None)
+
+ return (current_user_ref, tenant_ref, metadata_ref, expiry, bind)
def _authenticate_local(self, context, auth):
"""Try to authenticate against the identity backend.
@@ -283,30 +244,20 @@ class Auth(controller.V2Controller):
except exception.UserNotFound as e:
raise exception.Unauthorized(e)
- tenant_id = self._get_project_id_from_auth(auth)
-
try:
- auth_info = self.identity_api.authenticate(
+ user_ref = self.identity_api.authenticate(
user_id=user_id,
- password=password,
- tenant_id=tenant_id)
+ password=password)
except AssertionError as e:
raise exception.Unauthorized(e)
- (user_ref, tenant_ref, metadata_ref) = auth_info
- # By now we will have authorized and if a tenant/project was
- # specified, we will have obtained its metadata. In this case
- # we just need to add in any group roles.
- #
- # TODO(henry-nash): If no tenant was specified, instead check for a
- # domain and find any related user/group roles
-
- self._append_roles(metadata_ref,
- self._get_group_metadata_ref(
- context, user_id, tenant_id))
+ metadata_ref = {}
+ tenant_id = self._get_project_id_from_auth(auth)
+ tenant_ref, metadata_ref['roles'] = self._get_project_roles_and_ref(
+ user_id, tenant_id)
expiry = core.default_expire_time()
- return (user_ref, tenant_ref, metadata_ref, expiry)
+ return (user_ref, tenant_ref, metadata_ref, expiry, None)
def _authenticate_external(self, context, auth):
"""Try to authenticate an external user via REMOTE_USER variable.
@@ -316,6 +267,11 @@ class Auth(controller.V2Controller):
if 'REMOTE_USER' not in context:
raise ExternalAuthNotApplicable()
+ #NOTE(jamielennox): xml and json differ and get confused about what
+ # empty auth should look like so just reset it.
+ if not auth:
+ auth = {}
+
username = context['REMOTE_USER']
try:
user_ref = self.identity_api.get_user_by_name(
@@ -324,20 +280,18 @@ class Auth(controller.V2Controller):
except exception.UserNotFound as e:
raise exception.Unauthorized(e)
+ metadata_ref = {}
tenant_id = self._get_project_id_from_auth(auth)
-
- tenant_ref = self._get_project_ref(user_id, tenant_id)
- metadata_ref = self._get_metadata_ref(user_id, tenant_id)
-
- # TODO(henry-nash): If no tenant was specified, instead check for a
- # domain and find any related user/group roles
-
- self._append_roles(metadata_ref,
- self._get_group_metadata_ref(
- context, user_id, tenant_id))
+ tenant_ref, metadata_ref['roles'] = self._get_project_roles_and_ref(
+ user_id, tenant_id)
expiry = core.default_expire_time()
- return (user_ref, tenant_ref, metadata_ref, expiry)
+ bind = None
+ if ('kerberos' in CONF.token.bind and
+ context.get('AUTH_TYPE', '').lower() == 'negotiate'):
+ bind = {'kerberos': username}
+
+ return (user_ref, tenant_ref, metadata_ref, expiry, bind)
def _get_auth_token_data(self, user, tenant, metadata, expiry):
return dict(user=user,
@@ -405,40 +359,26 @@ class Auth(controller.V2Controller):
exception.Unauthorized(e)
return tenant_ref
- def _get_metadata_ref(self, user_id=None, tenant_id=None, domain_id=None,
- group_id=None):
- """Returns metadata_ref for a user or group in a tenant or domain."""
+ def _get_project_roles_and_ref(self, user_id, tenant_id):
+ """Returns the project roles for this user, and the project ref."""
- metadata_ref = {}
- if (user_id or group_id) and (tenant_id or domain_id):
+ tenant_ref = None
+ role_list = []
+ if tenant_id:
try:
- metadata_ref = self.identity_api.get_metadata(
- user_id=user_id, tenant_id=tenant_id,
- domain_id=domain_id, group_id=group_id)
- except exception.MetadataNotFound:
+ tenant_ref = self.identity_api.get_project(tenant_id)
+ role_list = self.identity_api.get_roles_for_user_and_project(
+ user_id, tenant_id)
+ except exception.ProjectNotFound:
pass
- return metadata_ref
-
- def _get_group_metadata_ref(self, context, user_id,
- tenant_id=None, domain_id=None):
- """Return any metadata for this project/domain due to group grants."""
- group_refs = self.identity_api.list_groups_for_user(user_id)
- metadata_ref = {}
- for x in group_refs:
- metadata_ref.update(self._get_metadata_ref(
- group_id=x['id'], tenant_id=tenant_id, domain_id=domain_id))
- return metadata_ref
- def _append_roles(self, metadata, additional_metadata):
- """Add additional roles to the roles in metadata.
-
- The final set of roles represents the union of existing roles and
- additional roles.
- """
+ if not role_list:
+ msg = _('User %(u_id)s is unauthorized for tenant %(t_id)s')
+ msg = msg % {'u_id': user_id, 't_id': tenant_id}
+ LOG.warning(msg)
+ raise exception.Unauthorized(msg)
- first = set(metadata.get('roles', []))
- second = set(additional_metadata.get('roles', []))
- metadata['roles'] = list(first.union(second))
+ return (tenant_ref, role_list)
def _get_token_ref(self, token_id, belongs_to=None):
"""Returns a token if a valid one exists.
@@ -456,45 +396,6 @@ class Auth(controller.V2Controller):
_('Token does not belong to specified tenant.'))
return data
- def _assert_default_domain(self, token_ref):
- """Make sure we are operating on default domain only."""
- if token_ref.get('token_data'):
- # this is a V3 token
- msg = _('Non-default domain is not supported')
- # user in a non-default is prohibited
- if (token_ref['token_data']['token']['user']['domain']['id'] !=
- DEFAULT_DOMAIN_ID):
- raise exception.Unauthorized(msg)
- # domain scoping is prohibited
- if token_ref['token_data']['token'].get('domain'):
- raise exception.Unauthorized(
- _('Domain scoped token is not supported'))
- # project in non-default domain is prohibited
- if token_ref['token_data']['token'].get('project'):
- project = token_ref['token_data']['token']['project']
- project_domain_id = project['domain']['id']
- # scoped to project in non-default domain is prohibited
- if project_domain_id != DEFAULT_DOMAIN_ID:
- raise exception.Unauthorized(msg)
- # if token is scoped to trust, both trustor and trustee must
- # be in the default domain. Furthermore, the delegated project
- # must also be in the default domain
- metadata_ref = token_ref['metadata']
- if CONF.trust.enabled and 'trust_id' in metadata_ref:
- trust_ref = self.trust_api.get_trust(metadata_ref['trust_id'])
- trustee_user_ref = self.identity_api.get_user(
- trust_ref['trustee_user_id'])
- if trustee_user_ref['domain_id'] != DEFAULT_DOMAIN_ID:
- raise exception.Unauthorized(msg)
- trustor_user_ref = self.identity_api.get_user(
- trust_ref['trustor_user_id'])
- if trustor_user_ref['domain_id'] != DEFAULT_DOMAIN_ID:
- raise exception.Unauthorized(msg)
- project_ref = self.identity_api.get_project(
- trust_ref['project_id'])
- if project_ref['domain_id'] != DEFAULT_DOMAIN_ID:
- raise exception.Unauthorized(msg)
-
@controller.protected
def validate_token_head(self, context, token_id):
"""Check that a token is valid.
@@ -505,9 +406,9 @@ class Auth(controller.V2Controller):
"""
belongs_to = context['query_string'].get('belongsTo')
- token_ref = self._get_token_ref(token_id, belongs_to)
- assert token_ref
- self._assert_default_domain(token_ref)
+ self.token_provider_api.check_token(token_id,
+ belongs_to=belongs_to,
+ version=token_provider.V2)
@controller.protected
def validate_token(self, context, token_id):
@@ -519,26 +420,9 @@ class Auth(controller.V2Controller):
"""
belongs_to = context['query_string'].get('belongsTo')
- token_ref = self._get_token_ref(token_id, belongs_to)
- self._assert_default_domain(token_ref)
-
- # TODO(termie): optimize this call at some point and put it into the
- # the return for metadata
- # fill out the roles in the metadata
- metadata_ref = token_ref['metadata']
- roles_ref = []
- for role_id in metadata_ref.get('roles', []):
- roles_ref.append(self.identity_api.get_role(role_id))
-
- # Get a service catalog if possible
- # This is needed for on-behalf-of requests
- catalog_ref = None
- if token_ref.get('tenant'):
- catalog_ref = self.catalog_api.get_catalog(
- user_id=token_ref['user']['id'],
- tenant_id=token_ref['tenant']['id'],
- metadata=metadata_ref)
- return Auth.format_token(token_ref, roles_ref, catalog_ref)
+ return self.token_provider_api.validate_token(
+ token_id, belongs_to=belongs_to,
+ version=token_provider.V2)
def delete_token(self, context, token_id):
"""Delete a token, effectively invalidating it for authz."""
@@ -571,106 +455,13 @@ class Auth(controller.V2Controller):
catalog_ref = None
if token_ref.get('tenant'):
catalog_ref = self.catalog_api.get_catalog(
- user_id=token_ref['user']['id'],
- tenant_id=token_ref['tenant']['id'],
- metadata=token_ref['metadata'])
+ token_ref['user']['id'],
+ token_ref['tenant']['id'],
+ token_ref['metadata'])
return Auth.format_endpoint_list(catalog_ref)
@classmethod
- def format_authenticate(cls, token_ref, roles_ref, catalog_ref):
- o = Auth.format_token(token_ref, roles_ref)
- o['access']['serviceCatalog'] = Auth.format_catalog(catalog_ref)
- return o
-
- @classmethod
- def format_token(cls, token_ref, roles_ref, catalog_ref=None):
- user_ref = token_ref['user']
- metadata_ref = token_ref['metadata']
- expires = token_ref['expires']
- if expires is not None:
- if not isinstance(expires, unicode):
- expires = timeutils.isotime(expires)
- o = {'access': {'token': {'id': token_ref['id'],
- 'expires': expires,
- 'issued_at': timeutils.strtime()
- },
- 'user': {'id': user_ref['id'],
- 'name': user_ref['name'],
- 'username': user_ref['name'],
- 'roles': roles_ref,
- 'roles_links': metadata_ref.get('roles_links',
- [])
- }
- }
- }
- if 'tenant' in token_ref and token_ref['tenant']:
- token_ref['tenant']['enabled'] = True
- o['access']['token']['tenant'] = token_ref['tenant']
- if catalog_ref is not None:
- o['access']['serviceCatalog'] = Auth.format_catalog(catalog_ref)
- if metadata_ref:
- if 'is_admin' in metadata_ref:
- o['access']['metadata'] = {'is_admin':
- metadata_ref['is_admin']}
- else:
- o['access']['metadata'] = {'is_admin': 0}
- if 'roles' in metadata_ref:
- o['access']['metadata']['roles'] = metadata_ref['roles']
- if CONF.trust.enabled and 'trust_id' in metadata_ref:
- o['access']['trust'] = {'trustee_user_id':
- metadata_ref['trustee_user_id'],
- 'id': metadata_ref['trust_id']
- }
- return o
-
- @classmethod
- def format_catalog(cls, catalog_ref):
- """Munge catalogs from internal to output format
- Internal catalogs look like:
-
- {$REGION: {
- {$SERVICE: {
- $key1: $value1,
- ...
- }
- }
- }
-
- The legacy api wants them to look like
-
- [{'name': $SERVICE[name],
- 'type': $SERVICE,
- 'endpoints': [{
- 'tenantId': $tenant_id,
- ...
- 'region': $REGION,
- }],
- 'endpoints_links': [],
- }]
-
- """
- if not catalog_ref:
- return []
-
- services = {}
- for region, region_ref in catalog_ref.iteritems():
- for service, service_ref in region_ref.iteritems():
- new_service_ref = services.get(service, {})
- new_service_ref['name'] = service_ref.pop('name')
- new_service_ref['type'] = service
- new_service_ref['endpoints_links'] = []
- service_ref['region'] = region
-
- endpoints_ref = new_service_ref.get('endpoints', [])
- endpoints_ref.append(service_ref)
-
- new_service_ref['endpoints'] = endpoints_ref
- services[service] = new_service_ref
-
- return services.values()
-
- @classmethod
def format_endpoint_list(cls, catalog_ref):
"""Formats a list of endpoints according to Identity API v2.
diff --git a/keystone/token/core.py b/keystone/token/core.py
index a8a3b82d..bc27b80d 100644
--- a/keystone/token/core.py
+++ b/keystone/token/core.py
@@ -16,6 +16,7 @@
"""Main entry point into the Token service."""
+import copy
import datetime
from keystone.common import cms
@@ -32,19 +33,6 @@ config.register_int('expiration', group='token', default=86400)
LOG = logging.getLogger(__name__)
-def unique_id(token_id):
- """Return a unique ID for a token.
-
- The returned value is useful as the primary key of a database table,
- memcache store, or other lookup table.
-
- :returns: Given a PKI token, returns it's hashed value. Otherwise, returns
- the passed-in value (such as a UUID token ID or an existing
- hash).
- """
- return cms.cms_hash_token(token_id)
-
-
def default_expire_time():
"""Determine when a fresh token should expire.
@@ -114,6 +102,29 @@ class Manager(manager.Manager):
def __init__(self):
super(Manager, self).__init__(CONF.token.driver)
+ def _unique_id(self, token_id):
+ """Return a unique ID for a token.
+
+ The returned value is useful as the primary key of a database table,
+ memcache store, or other lookup table.
+
+ :returns: Given a PKI token, returns it's hashed value. Otherwise,
+ returns the passed-in value (such as a UUID token ID or an
+ existing hash).
+ """
+ return cms.cms_hash_token(token_id)
+
+ def get_token(self, token_id):
+ return self.driver.get_token(self._unique_id(token_id))
+
+ def create_token(self, token_id, data):
+ data_copy = copy.deepcopy(data)
+ data_copy['id'] = self._unique_id(token_id)
+ return self.driver.create_token(self._unique_id(token_id), data_copy)
+
+ def delete_token(self, token_id):
+ return self.driver.delete_token(self._unique_id(token_id))
+
class Driver(object):
"""Interface description for a Token driver."""
diff --git a/keystone/token/provider.py b/keystone/token/provider.py
new file mode 100644
index 00000000..2864be6f
--- /dev/null
+++ b/keystone/token/provider.py
@@ -0,0 +1,177 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+"""Token provider interface."""
+
+
+from keystone.common import dependency
+from keystone.common import logging
+from keystone.common import manager
+from keystone import config
+from keystone import exception
+
+
+CONF = config.CONF
+LOG = logging.getLogger(__name__)
+
+
+# supported token versions
+V2 = 'v2.0'
+V3 = 'v3.0'
+
+# default token providers
+PKI_PROVIDER = 'keystone.token.providers.pki.Provider'
+UUID_PROVIDER = 'keystone.token.providers.uuid.Provider'
+
+
+class UnsupportedTokenVersionException(Exception):
+ """Token version is unrecognizable or unsupported."""
+ pass
+
+
+@dependency.provider('token_provider_api')
+class Manager(manager.Manager):
+ """Default pivot point for the token provider backend.
+
+ See :mod:`keystone.common.manager.Manager` for more details on how this
+ dynamically calls the backend.
+
+ """
+
+ @classmethod
+ def get_token_provider(cls):
+ """Return package path to the configured token provider.
+
+ The value should come from ``keystone.conf`` ``[token] provider``,
+ however this method ensures backwards compatibility for
+ ``keystone.conf`` ``[signing] token_format`` until Havana + 2.
+
+ Return the provider based on ``token_format`` if ``provider`` is not
+ set. Otherwise, ignore ``token_format`` and return the configured
+ ``provider`` instead.
+
+ """
+ if CONF.token.provider is not None:
+ # NOTE(gyee): we are deprecating CONF.signing.token_format. This
+ # code is to ensure the token provider configuration agrees with
+ # CONF.signing.token_format.
+ if ((CONF.signing.token_format == 'PKI' and
+ CONF.token.provider != PKI_PROVIDER or
+ (CONF.signing.token_format == 'UUID' and
+ CONF.token.provider != UUID_PROVIDER))):
+ raise exception.UnexpectedError(
+ _('keystone.conf [signing] token_format (deprecated) '
+ 'conflicts with keystone.conf [token] provider'))
+ return CONF.token.provider
+ else:
+ if not CONF.signing.token_format:
+ # No token provider and no format, so use default (PKI)
+ return PKI_PROVIDER
+
+ msg = _('keystone.conf [signing] token_format is deprecated in '
+ 'favor of keystone.conf [token] provider')
+ if CONF.signing.token_format == 'PKI':
+ LOG.warning(msg)
+ return PKI_PROVIDER
+ elif CONF.signing.token_format == 'UUID':
+ LOG.warning(msg)
+ return UUID_PROVIDER
+ else:
+ raise exception.UnexpectedError(
+ _('Unrecognized keystone.conf [signing] token_format: '
+ 'expected either \'UUID\' or \'PKI\''))
+
+ def __init__(self):
+ super(Manager, self).__init__(self.get_token_provider())
+
+
+class Provider(object):
+ """Interface description for a Token provider."""
+
+ def get_token_version(self, token_data):
+ """Return the version of the given token data.
+
+ If the given token data is unrecognizable,
+ UnsupportedTokenVersionException is raised.
+
+ """
+ raise exception.NotImplemented()
+
+ def issue_token(self, version='v3.0', **kwargs):
+ """Issue a V3 token.
+
+ For V3 tokens, 'user_id', 'method_names', must present in kwargs.
+ Optionally, kwargs may contain 'expires_at' for rescope tokens;
+ 'project_id' for project-scoped token; 'domain_id' for
+ domain-scoped token; and 'auth_context' from the authentication
+ plugins.
+
+ For V2 tokens, 'token_ref' must be present in kwargs.
+ Optionally, kwargs may contain 'roles_ref' and 'catalog_ref'.
+
+ :param context: request context
+ :type context: dictionary
+ :param version: version of the token to be issued
+ :type version: string
+ :param kwargs: information needed for token creation. Parameters
+ may be different depending on token version.
+ :type kwargs: dictionary
+ :returns: (token_id, token_data)
+
+ """
+ raise exception.NotImplemented()
+
+ def revoke_token(self, token_id):
+ """Revoke a given token.
+
+ :param token_id: identity of the token
+ :type token_id: string
+ :returns: None.
+ """
+ raise exception.NotImplemented()
+
+ def validate_token(self, token_id, belongs_to=None, version='v3.0'):
+ """Validate the given token and return the token data.
+
+ Must raise Unauthorized exception if unable to validate token.
+
+ :param token_id: identity of the token
+ :type token_id: string
+ :param belongs_to: identity of the scoped project to validate
+ :type belongs_to: string
+ :param version: version of the token to be validated
+ :type version: string
+ :returns: token data
+ :raises: keystone.exception.Unauthorized
+
+ """
+ raise exception.NotImplemented()
+
+ def check_token(self, token_id, belongs_to=None, version='v3.0'):
+ """Check the validity of the given V3 token.
+
+ Must raise Unauthorized exception if unable to check token.
+
+ :param token_id: identity of the token
+ :type token_id: string
+ :param belongs_to: identity of the scoped project to validate
+ :type belongs_to: string
+ :param version: version of the token to check
+ :type version: string
+ :returns: None
+ :raises: keystone.exception.Unauthorized
+
+ """
diff --git a/keystone/token/providers/__init__.py b/keystone/token/providers/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/keystone/token/providers/__init__.py
diff --git a/keystone/token/providers/pki.py b/keystone/token/providers/pki.py
new file mode 100644
index 00000000..81abe5d4
--- /dev/null
+++ b/keystone/token/providers/pki.py
@@ -0,0 +1,44 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 OpenStack LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+"""Keystone PKI Token Provider"""
+
+import json
+
+from keystone.common import cms
+from keystone.common import environment
+from keystone.common import logging
+from keystone import config
+from keystone import exception
+from keystone.token.providers import uuid
+
+
+CONF = config.CONF
+
+LOG = logging.getLogger(__name__)
+
+
+class Provider(uuid.Provider):
+ def _get_token_id(self, token_data):
+ try:
+ token_id = cms.cms_sign_token(json.dumps(token_data),
+ CONF.signing.certfile,
+ CONF.signing.keyfile)
+ return token_id
+ except environment.subprocess.CalledProcessError:
+ LOG.exception('Unable to sign token')
+ raise exception.UnexpectedError(_(
+ 'Unable to sign token.'))
diff --git a/keystone/token/providers/uuid.py b/keystone/token/providers/uuid.py
new file mode 100644
index 00000000..acfa9372
--- /dev/null
+++ b/keystone/token/providers/uuid.py
@@ -0,0 +1,577 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 OpenStack LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+"""Keystone UUID Token Provider"""
+
+from __future__ import absolute_import
+
+import sys
+import uuid
+
+from keystone.common import dependency
+from keystone.common import logging
+from keystone import config
+from keystone import exception
+from keystone.openstack.common import timeutils
+from keystone import token
+from keystone import trust
+
+
+LOG = logging.getLogger(__name__)
+CONF = config.CONF
+DEFAULT_DOMAIN_ID = CONF.identity.default_domain_id
+
+
+@dependency.requires('catalog_api', 'identity_api')
+class V2TokenDataHelper(object):
+ """Creates V2 token data."""
+ @classmethod
+ def format_token(cls, token_ref, roles_ref, catalog_ref=None):
+ user_ref = token_ref['user']
+ metadata_ref = token_ref['metadata']
+ expires = token_ref.get('expires', token.default_expire_time())
+ if expires is not None:
+ if not isinstance(expires, unicode):
+ expires = timeutils.isotime(expires)
+ o = {'access': {'token': {'id': token_ref['id'],
+ 'expires': expires,
+ 'issued_at': timeutils.strtime()
+ },
+ 'user': {'id': user_ref['id'],
+ 'name': user_ref['name'],
+ 'username': user_ref['name'],
+ 'roles': roles_ref,
+ 'roles_links': metadata_ref.get('roles_links',
+ [])
+ }
+ }
+ }
+ if 'bind' in token_ref:
+ o['access']['token']['bind'] = token_ref['bind']
+ if 'tenant' in token_ref and token_ref['tenant']:
+ token_ref['tenant']['enabled'] = True
+ o['access']['token']['tenant'] = token_ref['tenant']
+ if catalog_ref is not None:
+ o['access']['serviceCatalog'] = V2TokenDataHelper.format_catalog(
+ catalog_ref)
+ if metadata_ref:
+ if 'is_admin' in metadata_ref:
+ o['access']['metadata'] = {'is_admin':
+ metadata_ref['is_admin']}
+ else:
+ o['access']['metadata'] = {'is_admin': 0}
+ if 'roles' in metadata_ref:
+ o['access']['metadata']['roles'] = metadata_ref['roles']
+ if CONF.trust.enabled and 'trust_id' in metadata_ref:
+ o['access']['trust'] = {'trustee_user_id':
+ metadata_ref['trustee_user_id'],
+ 'id': metadata_ref['trust_id']
+ }
+ return o
+
+ @classmethod
+ def format_catalog(cls, catalog_ref):
+ """Munge catalogs from internal to output format
+ Internal catalogs look like:
+
+ {$REGION: {
+ {$SERVICE: {
+ $key1: $value1,
+ ...
+ }
+ }
+ }
+
+ The legacy api wants them to look like
+
+ [{'name': $SERVICE[name],
+ 'type': $SERVICE,
+ 'endpoints': [{
+ 'tenantId': $tenant_id,
+ ...
+ 'region': $REGION,
+ }],
+ 'endpoints_links': [],
+ }]
+
+ """
+ if not catalog_ref:
+ return []
+
+ services = {}
+ for region, region_ref in catalog_ref.iteritems():
+ for service, service_ref in region_ref.iteritems():
+ new_service_ref = services.get(service, {})
+ new_service_ref['name'] = service_ref.pop('name')
+ new_service_ref['type'] = service
+ new_service_ref['endpoints_links'] = []
+ service_ref['region'] = region
+
+ endpoints_ref = new_service_ref.get('endpoints', [])
+ endpoints_ref.append(service_ref)
+
+ new_service_ref['endpoints'] = endpoints_ref
+ services[service] = new_service_ref
+
+ return services.values()
+
+ @classmethod
+ def get_token_data(cls, **kwargs):
+ if 'token_ref' not in kwargs:
+ raise ValueError('Require token_ref to create V2 token data')
+ token_ref = kwargs.get('token_ref')
+ roles_ref = kwargs.get('roles_ref', [])
+ catalog_ref = kwargs.get('catalog_ref')
+ return V2TokenDataHelper.format_token(
+ token_ref, roles_ref, catalog_ref)
+
+
+@dependency.requires('catalog_api', 'identity_api')
+class V3TokenDataHelper(object):
+ """Token data helper."""
+ def __init__(self):
+ if CONF.trust.enabled:
+ self.trust_api = trust.Manager()
+
+ def _get_filtered_domain(self, domain_id):
+ domain_ref = self.identity_api.get_domain(domain_id)
+ return {'id': domain_ref['id'], 'name': domain_ref['name']}
+
+ def _get_filtered_project(self, project_id):
+ project_ref = self.identity_api.get_project(project_id)
+ filtered_project = {
+ 'id': project_ref['id'],
+ 'name': project_ref['name']}
+ filtered_project['domain'] = self._get_filtered_domain(
+ project_ref['domain_id'])
+ return filtered_project
+
+ def _populate_scope(self, token_data, domain_id, project_id):
+ if 'domain' in token_data or 'project' in token_data:
+ # scope already exist, no need to populate it again
+ return
+
+ if domain_id:
+ token_data['domain'] = self._get_filtered_domain(domain_id)
+ if project_id:
+ token_data['project'] = self._get_filtered_project(project_id)
+
+ def _get_roles_for_user(self, user_id, domain_id, project_id):
+ roles = []
+ if domain_id:
+ roles = self.identity_api.get_roles_for_user_and_domain(
+ user_id, domain_id)
+ if project_id:
+ roles = self.identity_api.get_roles_for_user_and_project(
+ user_id, project_id)
+ return [self.identity_api.get_role(role_id) for role_id in roles]
+
+ def _populate_user(self, token_data, user_id, domain_id, project_id,
+ trust):
+ if 'user' in token_data:
+ # no need to repopulate user if it already exists
+ return
+
+ user_ref = self.identity_api.get_user(user_id)
+ if CONF.trust.enabled and trust and 'OS-TRUST:trust' not in token_data:
+ trustor_user_ref = (self.identity_api.get_user(
+ trust['trustor_user_id']))
+ if not trustor_user_ref['enabled']:
+ raise exception.Forbidden(_('Trustor is disabled.'))
+ if trust['impersonation']:
+ user_ref = trustor_user_ref
+ token_data['OS-TRUST:trust'] = (
+ {
+ 'id': trust['id'],
+ 'trustor_user': {'id': trust['trustor_user_id']},
+ 'trustee_user': {'id': trust['trustee_user_id']},
+ 'impersonation': trust['impersonation']
+ })
+ filtered_user = {
+ 'id': user_ref['id'],
+ 'name': user_ref['name'],
+ 'domain': self._get_filtered_domain(user_ref['domain_id'])}
+ token_data['user'] = filtered_user
+
+ def _populate_roles(self, token_data, user_id, domain_id, project_id,
+ trust):
+ if 'roles' in token_data:
+ # no need to repopulate roles
+ return
+
+ if CONF.trust.enabled and trust:
+ token_user_id = trust['trustor_user_id']
+ token_project_id = trust['project_id']
+ #trusts do not support domains yet
+ token_domain_id = None
+ else:
+ token_user_id = user_id
+ token_project_id = project_id
+ token_domain_id = domain_id
+
+ if token_domain_id or token_project_id:
+ roles = self._get_roles_for_user(token_user_id,
+ token_domain_id,
+ token_project_id)
+ filtered_roles = []
+ if CONF.trust.enabled and trust:
+ for trust_role in trust['roles']:
+ match_roles = [x for x in roles
+ if x['id'] == trust_role['id']]
+ if match_roles:
+ filtered_roles.append(match_roles[0])
+ else:
+ raise exception.Forbidden(
+ _('Trustee has no delegated roles.'))
+ else:
+ for role in roles:
+ filtered_roles.append({'id': role['id'],
+ 'name': role['name']})
+
+ # user has no project or domain roles, therefore access denied
+ if not filtered_roles:
+ if token_project_id:
+ msg = _('User %(user_id)s has no access '
+ 'to project %(project_id)s') % {
+ 'user_id': user_id,
+ 'project_id': token_project_id}
+ else:
+ msg = _('User %(user_id)s has no access '
+ 'to domain %(domain_id)s') % {
+ 'user_id': user_id,
+ 'domain_id': token_domain_id}
+ LOG.debug(msg)
+ raise exception.Unauthorized(msg)
+
+ token_data['roles'] = filtered_roles
+
+ def _populate_service_catalog(self, token_data, user_id,
+ domain_id, project_id, trust):
+ if 'catalog' in token_data:
+ # no need to repopulate service catalog
+ return
+
+ if CONF.trust.enabled and trust:
+ user_id = trust['trustor_user_id']
+ if project_id or domain_id:
+ try:
+ service_catalog = self.catalog_api.get_v3_catalog(
+ user_id, project_id)
+ # TODO(ayoung): KVS backend needs a sample implementation
+ except exception.NotImplemented:
+ service_catalog = {}
+ # TODO(gyee): v3 service catalog is not quite completed yet
+ # TODO(ayoung): Enforce Endpoints for trust
+ token_data['catalog'] = service_catalog
+
+ def _populate_token_dates(self, token_data, expires=None, trust=None):
+ if not expires:
+ expires = token.default_expire_time()
+ if not isinstance(expires, basestring):
+ expires = timeutils.isotime(expires, subsecond=True)
+ token_data['expires_at'] = expires
+ token_data['issued_at'] = timeutils.isotime(subsecond=True)
+
+ def get_token_data(self, user_id, method_names, extras,
+ domain_id=None, project_id=None, expires=None,
+ trust=None, token=None, include_catalog=True,
+ bind=None):
+ token_data = {'methods': method_names,
+ 'extras': extras}
+
+ # We've probably already written these to the token
+ if token:
+ for x in ('roles', 'user', 'catalog', 'project', 'domain'):
+ if x in token:
+ token_data[x] = token[x]
+
+ if CONF.trust.enabled and trust:
+ if user_id != trust['trustee_user_id']:
+ raise exception.Forbidden(_('User is not a trustee.'))
+
+ if bind:
+ token_data['bind'] = bind
+
+ self._populate_scope(token_data, domain_id, project_id)
+ self._populate_user(token_data, user_id, domain_id, project_id, trust)
+ self._populate_roles(token_data, user_id, domain_id, project_id, trust)
+ if include_catalog:
+ self._populate_service_catalog(token_data, user_id, domain_id,
+ project_id, trust)
+ self._populate_token_dates(token_data, expires=expires, trust=trust)
+ return {'token': token_data}
+
+
+@dependency.requires('token_api', 'identity_api', 'catalog_api')
+class Provider(token.provider.Provider):
+ def __init__(self, *args, **kwargs):
+ super(Provider, self).__init__(*args, **kwargs)
+ if CONF.trust.enabled:
+ self.trust_api = trust.Manager()
+ self.v3_token_data_helper = V3TokenDataHelper()
+ self.v2_token_data_helper = V2TokenDataHelper()
+
+ def get_token_version(self, token_data):
+ if token_data and isinstance(token_data, dict):
+ if 'access' in token_data:
+ return token.provider.V2
+ if 'token' in token_data and 'methods' in token_data['token']:
+ return token.provider.V3
+ raise token.provider.UnsupportedTokenVersionException()
+
+ def _get_token_id(self, token_data):
+ return uuid.uuid4().hex
+
+ def _issue_v2_token(self, **kwargs):
+ token_data = self.v2_token_data_helper.get_token_data(**kwargs)
+ token_id = self._get_token_id(token_data)
+ token_data['access']['token']['id'] = token_id
+ try:
+ expiry = token_data['access']['token']['expires']
+ token_ref = kwargs.get('token_ref')
+ if isinstance(expiry, basestring):
+ expiry = timeutils.normalize_time(
+ timeutils.parse_isotime(expiry))
+ data = dict(key=token_id,
+ id=token_id,
+ expires=expiry,
+ user=token_ref['user'],
+ tenant=token_ref['tenant'],
+ metadata=token_ref['metadata'],
+ token_data=token_data,
+ bind=token_ref.get('bind'),
+ trust_id=token_ref['metadata'].get('trust_id'))
+ self.token_api.create_token(token_id, data)
+ except Exception:
+ exc_info = sys.exc_info()
+ # an identical token may have been created already.
+ # if so, return the token_data as it is also identical
+ try:
+ self.token_api.get_token(token_id)
+ except exception.TokenNotFound:
+ raise exc_info[0], exc_info[1], exc_info[2]
+
+ return (token_id, token_data)
+
+ def _issue_v3_token(self, **kwargs):
+ user_id = kwargs.get('user_id')
+ method_names = kwargs.get('method_names')
+ expires_at = kwargs.get('expires_at')
+ project_id = kwargs.get('project_id')
+ domain_id = kwargs.get('domain_id')
+ auth_context = kwargs.get('auth_context')
+ trust = kwargs.get('trust')
+ metadata_ref = kwargs.get('metadata_ref')
+ include_catalog = kwargs.get('include_catalog')
+ # for V2, trust is stashed in metadata_ref
+ if (CONF.trust.enabled and not trust and metadata_ref and
+ 'trust_id' in metadata_ref):
+ trust = self.trust_api.get_trust(metadata_ref['trust_id'])
+ token_data = self.v3_token_data_helper.get_token_data(
+ user_id,
+ method_names,
+ auth_context.get('extras') if auth_context else None,
+ domain_id=domain_id,
+ project_id=project_id,
+ expires=expires_at,
+ trust=trust,
+ bind=auth_context.get('bind') if auth_context else None,
+ include_catalog=include_catalog)
+
+ token_id = self._get_token_id(token_data)
+ try:
+ expiry = token_data['token']['expires_at']
+ if isinstance(expiry, basestring):
+ expiry = timeutils.normalize_time(
+ timeutils.parse_isotime(expiry))
+ # FIXME(gyee): is there really a need to store roles in metadata?
+ role_ids = []
+ metadata_ref = kwargs.get('metadata_ref', {})
+ if 'project' in token_data['token']:
+ # project-scoped token, fill in the v2 token data
+ # all we care are the role IDs
+ role_ids = [r['id'] for r in token_data['token']['roles']]
+ metadata_ref = {'roles': role_ids}
+ if trust:
+ metadata_ref.setdefault('trust_id', trust['id'])
+ metadata_ref.setdefault('trustee_user_id',
+ trust['trustee_user_id'])
+ data = dict(key=token_id,
+ id=token_id,
+ expires=expiry,
+ user=token_data['token']['user'],
+ tenant=token_data['token'].get('project'),
+ metadata=metadata_ref,
+ token_data=token_data,
+ trust_id=trust['id'] if trust else None)
+ self.token_api.create_token(token_id, data)
+ except Exception:
+ exc_info = sys.exc_info()
+ # an identical token may have been created already.
+ # if so, return the token_data as it is also identical
+ try:
+ self.token_api.get_token(token_id)
+ except exception.TokenNotFound:
+ raise exc_info[0], exc_info[1], exc_info[2]
+
+ return (token_id, token_data)
+
+ def issue_token(self, version='v3.0', **kwargs):
+ if version == token.provider.V3:
+ return self._issue_v3_token(**kwargs)
+ elif version == token.provider.V2:
+ return self._issue_v2_token(**kwargs)
+ raise token.provider.UnsupportedTokenVersionException
+
+ def _verify_token(self, token_id, belongs_to=None):
+ """Verify the given token and return the token_ref."""
+ token_ref = self.token_api.get_token(token_id)
+ assert token_ref
+ if belongs_to:
+ assert (token_ref['tenant'] and
+ token_ref['tenant']['id'] == belongs_to)
+ return token_ref
+
+ def revoke_token(self, token_id):
+ self.token_api.delete_token(token_id=token_id)
+
+ def _assert_default_domain(self, token_ref):
+ """Make sure we are operating on default domain only."""
+ if (token_ref.get('token_data') and
+ self.get_token_version(token_ref.get('token_data')) ==
+ token.provider.V3):
+ # this is a V3 token
+ msg = _('Non-default domain is not supported')
+ # user in a non-default is prohibited
+ if (token_ref['token_data']['token']['user']['domain']['id'] !=
+ DEFAULT_DOMAIN_ID):
+ raise exception.Unauthorized(msg)
+ # domain scoping is prohibited
+ if token_ref['token_data']['token'].get('domain'):
+ raise exception.Unauthorized(
+ _('Domain scoped token is not supported'))
+ # project in non-default domain is prohibited
+ if token_ref['token_data']['token'].get('project'):
+ project = token_ref['token_data']['token']['project']
+ project_domain_id = project['domain']['id']
+ # scoped to project in non-default domain is prohibited
+ if project_domain_id != DEFAULT_DOMAIN_ID:
+ raise exception.Unauthorized(msg)
+ # if token is scoped to trust, both trustor and trustee must
+ # be in the default domain. Furthermore, the delegated project
+ # must also be in the default domain
+ metadata_ref = token_ref['metadata']
+ if CONF.trust.enabled and 'trust_id' in metadata_ref:
+ trust_ref = self.trust_api.get_trust(metadata_ref['trust_id'])
+ trustee_user_ref = self.identity_api.get_user(
+ trust_ref['trustee_user_id'])
+ if trustee_user_ref['domain_id'] != DEFAULT_DOMAIN_ID:
+ raise exception.Unauthorized(msg)
+ trustor_user_ref = self.identity_api.get_user(
+ trust_ref['trustor_user_id'])
+ if trustor_user_ref['domain_id'] != DEFAULT_DOMAIN_ID:
+ raise exception.Unauthorized(msg)
+ project_ref = self.identity_api.get_project(
+ trust_ref['project_id'])
+ if project_ref['domain_id'] != DEFAULT_DOMAIN_ID:
+ raise exception.Unauthorized(msg)
+
+ def _validate_v2_token(self, token_id, belongs_to=None, **kwargs):
+ try:
+ token_ref = self._verify_token(token_id, belongs_to=belongs_to)
+ self._assert_default_domain(token_ref)
+ # FIXME(gyee): performance or correctness? Should we return the
+ # cached token or reconstruct it? Obviously if we are going with
+ # the cached token, any role, project, or domain name changes
+ # will not be reflected. One may argue that with PKI tokens,
+ # we are essentially doing cached token validation anyway.
+ # Lets go with the cached token strategy. Since token
+ # management layer is now pluggable, one can always provide
+ # their own implementation to suit their needs.
+ token_data = token_ref.get('token_data')
+ if (not token_data or
+ self.get_token_version(token_data) !=
+ token.provider.V2):
+ # token is created by old v2 logic
+ metadata_ref = token_ref['metadata']
+ role_refs = []
+ for role_id in metadata_ref.get('roles', []):
+ role_refs.append(self.identity_api.get_role(role_id))
+
+ # Get a service catalog if possible
+ # This is needed for on-behalf-of requests
+ catalog_ref = None
+ if token_ref.get('tenant'):
+ catalog_ref = self.catalog_api.get_catalog(
+ token_ref['user']['id'],
+ token_ref['tenant']['id'],
+ metadata_ref)
+ token_data = self.v2_token_data_helper.get_token_data(
+ token_ref=token_ref,
+ roles_ref=role_refs,
+ catalog_ref=catalog_ref)
+ return token_data
+ except AssertionError as e:
+ LOG.exception(_('Failed to validate token'))
+ raise exception.Unauthorized(e)
+
+ def _validate_v3_token(self, token_id):
+ token_ref = self._verify_token(token_id)
+ # FIXME(gyee): performance or correctness? Should we return the
+ # cached token or reconstruct it? Obviously if we are going with
+ # the cached token, any role, project, or domain name changes
+ # will not be reflected. One may argue that with PKI tokens,
+ # we are essentially doing cached token validation anyway.
+ # Lets go with the cached token strategy. Since token
+ # management layer is now pluggable, one can always provide
+ # their own implementation to suit their needs.
+ token_data = token_ref.get('token_data')
+ if not token_data or 'token' not in token_data:
+ # token ref is created by V2 API
+ project_id = None
+ project_ref = token_ref.get('tenant')
+ if project_ref:
+ project_id = project_ref['id']
+ token_data = self.v3_token_data_helper.get_token_data(
+ token_ref['user']['id'],
+ ['password', 'token'],
+ {},
+ project_id=project_id,
+ bind=token_ref.get('bind'),
+ expires=token_ref['expires'])
+ return token_data
+
+ def validate_token(self, token_id, belongs_to=None, version='v3.0'):
+ try:
+ if version == token.provider.V3:
+ return self._validate_v3_token(token_id)
+ elif version == token.provider.V2:
+ return self._validate_v2_token(token_id,
+ belongs_to=belongs_to)
+ raise token.provider.UnsupportedTokenVersionException()
+ except exception.TokenNotFound as e:
+ LOG.exception(_('Failed to verify token'))
+ raise exception.Unauthorized(e)
+
+ def check_token(self, token_id, belongs_to=None,
+ version='v3.0', **kwargs):
+ try:
+ token_ref = self._verify_token(token_id, belongs_to=belongs_to)
+ if version == token.provider.V2:
+ self._assert_default_domain(token_ref)
+ except exception.TokenNotFound as e:
+ LOG.exception(_('Failed to verify token'))
+ raise exception.Unauthorized(e)
diff --git a/keystone/trust/controllers.py b/keystone/trust/controllers.py
index 7be6e8fd..7a94fe29 100644
--- a/keystone/trust/controllers.py
+++ b/keystone/trust/controllers.py
@@ -35,6 +35,21 @@ class TrustV3(controller.V3Controller):
collection_name = "trusts"
member_name = "trust"
+ @classmethod
+ def base_url(cls, path=None):
+ endpoint = CONF.public_endpoint % CONF
+
+ # allow a missing trailing slash in the config
+ if endpoint[-1] != '/':
+ endpoint += '/'
+
+ url = endpoint + 'v3/OS-TRUST'
+
+ if path:
+ return url + path
+ else:
+ return url + '/' + cls.collection_name
+
def _get_user_id(self, context):
if 'token_id' in context:
token_id = context['token_id']
@@ -78,8 +93,7 @@ class TrustV3(controller.V3Controller):
trust_full_roles.append(full_role)
trust['roles'] = trust_full_roles
trust['roles_links'] = {
- 'self': (CONF.public_endpoint % CONF +
- "trusts/%s/roles" % trust['id']),
+ 'self': (self.base_url() + "/%s/roles" % trust['id']),
'next': None,
'previous': None}
diff --git a/openstack-common.conf b/openstack-common.conf
index 170f200f..17062942 100644
--- a/openstack-common.conf
+++ b/openstack-common.conf
@@ -1,6 +1,7 @@
[DEFAULT]
# The list of modules to copy from openstack-common
+module=crypto
module=importutils
module=install_venv_common
module=jsonutils
diff --git a/requirements.txt b/requirements.txt
index 45054f24..e54bb6a0 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -13,5 +13,5 @@ sqlalchemy-migrate>=0.7.2
passlib
lxml
iso8601>=0.1.4
-python-keystoneclient>=0.2.1,<0.3
+python-keystoneclient>=0.3.0
oslo.config>=1.1.0
diff --git a/setup.cfg b/setup.cfg
index d217ee7c..83d43963 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,5 +1,6 @@
[metadata]
name = keystone
+version = 2013.2
summary = OpenStack Identity
description-file =
README.rst
diff --git a/test-requirements.txt b/test-requirements.txt
index 0f772cb0..e0534ca4 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -11,22 +11,31 @@ pysqlite
python-memcached
# Optional backend: LDAP
-python-ldap==2.3.13 # authenticate against an existing LDAP server
+# authenticate against an existing LDAP server
+python-ldap==2.3.13
# Testing
-coverage # computes code coverage percentages
-mox # mock object framework
-nose # for test discovery and console feedback
+# computes code coverage percentages
+coverage
+# mock object framework
+mox
+# for test discovery and console feedback
+nose
nosexcover
openstack.nose_plugin
nosehtmloutput
-Sphinx>=1.1.2 # required to build documentation
-unittest2 # backport of unittest lib in python 2.7
-webtest # test wsgi apps without starting an http server
+# required to build documentation
+Sphinx>=1.1.2
+# backport of unittest lib in python 2.7
+unittest2
+# test wsgi apps without starting an http server
+webtest
# for python-keystoneclient
-httplib2 # keystoneclient <0.2.1
-requests>=1.0.0 # replaces httplib2 in keystoneclient >=0.2.1
+# keystoneclient <0.2.1
+httplib2
+# replaces httplib2 in keystoneclient >=0.2.1
+requests>=1.0.0
keyring
# swift_auth test dependencies
@@ -35,3 +44,6 @@ netifaces
# For translations processing
Babel
+
+# For documentation
+oslo.sphinx
diff --git a/tests/_ldap_livetest.py b/tests/_ldap_livetest.py
index 0943f8d0..ead54ea7 100644
--- a/tests/_ldap_livetest.py
+++ b/tests/_ldap_livetest.py
@@ -16,7 +16,6 @@
import ldap
import ldap.modlist
-import nose.exc
import subprocess
from keystone.common import ldap as ldap_common
@@ -68,9 +67,6 @@ class LiveLDAPIdentity(test_backend_ldap.LDAPIdentity):
create_object(CONF.ldap.tenant_tree_dn,
{'objectclass': 'organizationalUnit',
'ou': 'Projects'})
- create_object(CONF.ldap.domain_tree_dn,
- {'objectclass': 'organizationalUnit',
- 'ou': 'Domains'})
create_object(CONF.ldap.group_tree_dn,
{'objectclass': 'organizationalUnit',
'ou': 'UserGroups'})
@@ -92,7 +88,7 @@ class LiveLDAPIdentity(test_backend_ldap.LDAPIdentity):
test.TestCase.tearDown(self)
def test_user_enable_attribute_mask(self):
- raise nose.exc.SkipTest('Test is for Active Directory Only')
+ self.skipTest('Test is for Active Directory Only')
def test_ldap_dereferencing(self):
alt_users_ldif = {'objectclass': ['top', 'organizationalUnit'],
diff --git a/tests/_sql_livetest.py b/tests/_sql_livetest.py
index d9890979..a271ce7c 100644
--- a/tests/_sql_livetest.py
+++ b/tests/_sql_livetest.py
@@ -35,3 +35,11 @@ class MysqlMigrateTests(test_sql_upgrade.SqlUpgradeTests):
_config_file_list[:])
files.append("backend_mysql.conf")
return files
+
+
+class Db2MigrateTests(test_sql_upgrade.SqlUpgradeTests):
+ def config_files(self):
+ files = (test_sql_upgrade.SqlUpgradeTests.
+ _config_file_list[:])
+ files.append("backend_db2.conf")
+ return files
diff --git a/tests/auth_plugin_external_disabled.conf b/tests/auth_plugin_external_disabled.conf
new file mode 100644
index 00000000..fed281d4
--- /dev/null
+++ b/tests/auth_plugin_external_disabled.conf
@@ -0,0 +1,2 @@
+[auth]
+methods = password, token
diff --git a/tests/auth_plugin_external_domain.conf b/tests/auth_plugin_external_domain.conf
new file mode 100644
index 00000000..b7be122f
--- /dev/null
+++ b/tests/auth_plugin_external_domain.conf
@@ -0,0 +1,3 @@
+[auth]
+methods = external, password, token
+external = keystone.auth.plugins.external.ExternalDomain
diff --git a/tests/backend_db2.conf b/tests/backend_db2.conf
new file mode 100644
index 00000000..44032255
--- /dev/null
+++ b/tests/backend_db2.conf
@@ -0,0 +1,4 @@
+#Used for running the Migrate tests against a live DB2 Server
+#See _sql_livetest.py
+[sql]
+connection = ibm_db_sa://keystone:keystone@/staktest?charset=utf8
diff --git a/tests/backend_ldap_sql.conf b/tests/backend_ldap_sql.conf
new file mode 100644
index 00000000..8dcfa40d
--- /dev/null
+++ b/tests/backend_ldap_sql.conf
@@ -0,0 +1,36 @@
+[sql]
+connection = sqlite://
+#For a file based sqlite use
+#connection = sqlite:////tmp/keystone.db
+#To Test MySQL:
+#connection = mysql://keystone:keystone@localhost/keystone?charset=utf8
+#To Test PostgreSQL:
+#connection = postgresql://keystone:keystone@localhost/keystone?client_encoding=utf8
+idle_timeout = 200
+
+[ldap]
+url = fake://memory
+user = cn=Admin
+password = password
+suffix = cn=example,cn=com
+
+[identity]
+driver = keystone.identity.backends.ldap.Identity
+
+[assignment]
+driver = keystone.assignment.backends.sql.Assignment
+
+[token]
+driver = keystone.token.backends.sql.Token
+
+[ec2]
+driver = keystone.contrib.ec2.backends.sql.Ec2
+
+[catalog]
+driver = keystone.catalog.backends.sql.Catalog
+
+[policy]
+driver = keystone.policy.backends.sql.Policy
+
+[trust]
+driver = keystone.trust.backends.sql.Trust
diff --git a/tests/backend_liveldap.conf b/tests/backend_liveldap.conf
index abcd441d..297d96d6 100644
--- a/tests/backend_liveldap.conf
+++ b/tests/backend_liveldap.conf
@@ -6,11 +6,9 @@ suffix = dc=openstack,dc=org
group_tree_dn = ou=UserGroups,dc=openstack,dc=org
role_tree_dn = ou=Roles,dc=openstack,dc=org
tenant_tree_dn = ou=Projects,dc=openstack,dc=org
-domain_tree_dn = ou=Domains,dc=openstack,dc=org
user_tree_dn = ou=Users,dc=openstack,dc=org
tenant_enabled_emulation = True
user_enabled_emulation = True
-domain_enabled_emulation = True
user_mail_attribute = mail
use_dumb_member = True
diff --git a/tests/backend_sql_disk.conf b/tests/backend_sql_disk.conf
index a4be9117..0f8dfea7 100644
--- a/tests/backend_sql_disk.conf
+++ b/tests/backend_sql_disk.conf
@@ -1,2 +1,2 @@
[sql]
-connection = sqlite:///test.db
+connection = sqlite:///tmp/test.db
diff --git a/tests/backend_tls_liveldap.conf b/tests/backend_tls_liveldap.conf
index 0c9d7f23..409af674 100644
--- a/tests/backend_tls_liveldap.conf
+++ b/tests/backend_tls_liveldap.conf
@@ -6,11 +6,9 @@ suffix = dc=openstack,dc=org
group_tree_dn = ou=UserGroups,dc=openstack,dc=org
role_tree_dn = ou=Roles,dc=openstack,dc=org
tenant_tree_dn = ou=Projects,dc=openstack,dc=org
-domain_tree_dn = ou=Domains,dc=openstack,dc=org
user_tree_dn = ou=Users,dc=openstack,dc=org
tenant_enabled_emulation = True
user_enabled_emulation = True
-domain_enabled_emulation = True
user_mail_attribute = mail
use_dumb_member = True
use_tls = True
diff --git a/tests/default_fixtures.py b/tests/default_fixtures.py
index 256bb4b7..2695da88 100644
--- a/tests/default_fixtures.py
+++ b/tests/default_fixtures.py
@@ -17,6 +17,7 @@
# NOTE(dolph): please try to avoid additional fixtures if possible; test suite
# performance may be negatively affected.
+from keystone import assignment
from keystone import config
@@ -54,7 +55,7 @@ TENANTS = [
}
]
-# NOTE(ja): a role of keystone_admin and attribute "is_admin" is done in setUp
+# NOTE(ja): a role of keystone_admin is done in setUp
USERS = [
{
'id': 'foo',
@@ -95,13 +96,6 @@ USERS = [
}
]
-METADATA = [
- {
- 'user_id': 'sna',
- 'tenant_id': 'mtu',
- }
-]
-
ROLES = [
{
'id': 'admin',
@@ -125,16 +119,6 @@ ROLES = [
'id': 'service',
'name': 'Service',
}
-
-
]
-DOMAINS = [
- {
- 'id': DEFAULT_DOMAIN_ID,
- 'name': 'Default',
- 'enabled': True,
- 'description': 'Owns users and tenants (i.e. projects) available '
- 'on Identity API v2.'
- }
-]
+DOMAINS = [assignment.DEFAULT_DOMAIN]
diff --git a/tests/test_auth.py b/tests/test_auth.py
index b14977b9..db5314be 100644
--- a/tests/test_auth.py
+++ b/tests/test_auth.py
@@ -68,6 +68,10 @@ class AuthTest(test.TestCase):
self.load_backends()
self.load_fixtures(default_fixtures)
+ # need to register the token provider first because auth controller
+ # depends on it
+ token.provider.Manager()
+
self.controller = token.controllers.Auth()
def assertEqualTokens(self, a, b):
@@ -369,6 +373,33 @@ class AuthWithToken(AuthTest):
dict(is_admin=True, query_string={'belongsTo': 'BAR'}),
token_id=scoped_token_id)
+ def test_token_auth_with_binding(self):
+ CONF.token.bind = ['kerberos']
+ body_dict = _build_user_auth()
+ context = {'REMOTE_USER': 'FOO', 'AUTH_TYPE': 'Negotiate'}
+ unscoped_token = self.controller.authenticate(context, body_dict)
+
+ # the token should have bind information in it
+ bind = unscoped_token['access']['token']['bind']
+ self.assertEqual(bind['kerberos'], 'FOO')
+
+ body_dict = _build_user_auth(
+ token=unscoped_token['access']['token'],
+ tenant_name='BAR')
+
+ # using unscoped token without remote user context fails
+ self.assertRaises(
+ exception.Unauthorized,
+ self.controller.authenticate,
+ {}, body_dict)
+
+ # using token with remote user context succeeds
+ scoped_token = self.controller.authenticate(context, body_dict)
+
+ # the bind information should be carried over from the original token
+ bind = scoped_token['access']['token']['bind']
+ self.assertEqual(bind['kerberos'], 'FOO')
+
class AuthWithPasswordCredentials(AuthTest):
def setUp(self):
@@ -427,6 +458,13 @@ class AuthWithPasswordCredentials(AuthTest):
self.controller.authenticate,
{}, body_dict)
+ def test_bind_without_remote_user(self):
+ CONF.token.bind = ['kerberos']
+ body_dict = _build_user_auth(username='FOO', password='foo2',
+ tenant_name='BAR')
+ token = self.controller.authenticate({}, body_dict)
+ self.assertNotIn('bind', token['access']['token'])
+
class AuthWithRemoteUser(AuthTest):
def setUp(self):
@@ -494,6 +532,20 @@ class AuthWithRemoteUser(AuthTest):
{'REMOTE_USER': uuid.uuid4().hex},
body_dict)
+ def test_bind_with_kerberos(self):
+ CONF.token.bind = ['kerberos']
+ kerb = {'REMOTE_USER': 'FOO', 'AUTH_TYPE': 'Negotiate'}
+ body_dict = _build_user_auth(tenant_name="BAR")
+ token = self.controller.authenticate(kerb, body_dict)
+ self.assertEqual(token['access']['token']['bind']['kerberos'], 'FOO')
+
+ def test_bind_without_config_opt(self):
+ CONF.token.bind = ['x509']
+ kerb = {'REMOTE_USER': 'FOO', 'AUTH_TYPE': 'Negotiate'}
+ body_dict = _build_user_auth(tenant_name='BAR')
+ token = self.controller.authenticate(kerb, body_dict)
+ self.assertNotIn('bind', token['access']['token'])
+
class AuthWithTrust(AuthTest):
def setUp(self):
@@ -566,6 +618,10 @@ class AuthWithTrust(AuthTest):
role_ids = [self.role_browser['id'], self.role_member['id']]
self.assertTrue(timeutils.parse_strtime(self.new_trust['expires_at'],
fmt=TIME_FORMAT))
+ self.assertIn('http://localhost:5000/v3/OS-TRUST/',
+ self.new_trust['links']['self'])
+ self.assertIn('http://localhost:5000/v3/OS-TRUST/',
+ self.new_trust['roles_links']['self'])
for role in self.new_trust['roles']:
self.assertIn(role['id'], role_ids)
@@ -621,7 +677,7 @@ class AuthWithTrust(AuthTest):
'project': {
'id': self.tenant_baz['id']}}}
auth_response = (self.auth_v3_controller.authenticate_for_token
- ({}, v3_password_data))
+ ({'query_string': {}}, v3_password_data))
token = auth_response.headers['X-Subject-Token']
v3_req_with_trust = {
@@ -631,7 +687,7 @@ class AuthWithTrust(AuthTest):
"scope": {
"OS-TRUST:trust": {"id": self.new_trust['id']}}}
token_auth_response = (self.auth_v3_controller.authenticate_for_token
- ({}, v3_req_with_trust))
+ ({'query_string': {}}, v3_req_with_trust))
return token_auth_response
def test_create_v3_token_from_trust(self):
@@ -653,14 +709,14 @@ class AuthWithTrust(AuthTest):
def test_v3_trust_token_get_token_fails(self):
auth_response = self.fetch_v3_token_from_trust()
trust_token = auth_response.headers['X-Subject-Token']
- v3_token_data = {
- "methods": ["token"],
- "token": {"id": trust_token}
- }
+ v3_token_data = {'identity': {
+ 'methods': ['token'],
+ 'token': {'id': trust_token}
+ }}
self.assertRaises(
- exception.Unauthorized,
+ exception.Forbidden,
self.auth_v3_controller.authenticate_for_token,
- {}, v3_token_data)
+ {'query_string': {}}, v3_token_data)
def test_token_from_trust(self):
auth_response = self.fetch_v2_token_from_trust()
diff --git a/tests/test_auth_plugin.conf b/tests/test_auth_plugin.conf
index efe4bcb4..edec8f79 100644
--- a/tests/test_auth_plugin.conf
+++ b/tests/test_auth_plugin.conf
@@ -1,3 +1,3 @@
[auth]
-methods = password,token,simple-challenge-response
+methods = external,password,token,simple-challenge-response
simple-challenge-response = challenge_response_method.SimpleChallengeResponse
diff --git a/tests/test_auth_plugin.py b/tests/test_auth_plugin.py
index 22357471..d158ec46 100644
--- a/tests/test_auth_plugin.py
+++ b/tests/test_auth_plugin.py
@@ -20,6 +20,7 @@ from keystone import test
from keystone import auth
from keystone import exception
+from keystone import token
# for testing purposes only
@@ -49,6 +50,11 @@ class TestAuthPlugin(test.TestCase):
test.testsdir('test_auth_plugin.conf')])
self.load_backends()
auth.controllers.AUTH_METHODS[METHOD_NAME] = SimpleChallengeResponse()
+
+ # need to register the token provider first because auth controller
+ # depends on it
+ token.provider.Manager()
+
self.api = auth.controllers.Auth()
def test_unsupported_auth_method(self):
diff --git a/tests/test_backend.py b/tests/test_backend.py
index ea40cd8b..7e4d820e 100644
--- a/tests/test_backend.py
+++ b/tests/test_backend.py
@@ -62,39 +62,17 @@ class IdentityTests(object):
self.assertRaises(AssertionError,
self.identity_api.authenticate,
user_id=uuid.uuid4().hex,
- tenant_id=self.tenant_bar['id'],
password=self.user_foo['password'])
def test_authenticate_bad_password(self):
self.assertRaises(AssertionError,
self.identity_api.authenticate,
user_id=self.user_foo['id'],
- tenant_id=self.tenant_bar['id'],
password=uuid.uuid4().hex)
- def test_authenticate_bad_project(self):
- self.assertRaises(AssertionError,
- self.identity_api.authenticate,
- user_id=self.user_foo['id'],
- tenant_id=uuid.uuid4().hex,
- password=self.user_foo['password'])
-
- def test_authenticate_no_project(self):
- user_ref, tenant_ref, metadata_ref = self.identity_api.authenticate(
- user_id=self.user_foo['id'],
- password=self.user_foo['password'])
- # NOTE(termie): the password field is left in user_foo to make
- # it easier to authenticate in tests, but should
- # not be returned by the api
- self.user_foo.pop('password')
- self.assertDictEqual(user_ref, self.user_foo)
- self.assert_(tenant_ref is None)
- self.assert_(not metadata_ref)
-
def test_authenticate(self):
- user_ref, tenant_ref, metadata_ref = self.identity_api.authenticate(
+ user_ref = self.identity_api.authenticate(
user_id=self.user_sna['id'],
- tenant_id=self.tenant_bar['id'],
password=self.user_sna['password'])
# NOTE(termie): the password field is left in user_foo to make
# it easier to authenticate in tests, but should
@@ -102,21 +80,8 @@ class IdentityTests(object):
self.user_sna.pop('password')
self.user_sna['enabled'] = True
self.assertDictEqual(user_ref, self.user_sna)
- self.assertDictEqual(tenant_ref, self.tenant_bar)
- metadata_ref.pop('roles')
- self.assertDictEqual(metadata_ref, self.metadata_snamtu)
-
- def test_authenticate_role_return(self):
- self.identity_api.add_role_to_user_and_project(
- self.user_foo['id'], self.tenant_baz['id'], self.role_admin['id'])
- user_ref, tenant_ref, metadata_ref = self.identity_api.authenticate(
- user_id=self.user_foo['id'],
- tenant_id=self.tenant_baz['id'],
- password=self.user_foo['password'])
- self.assertIn('roles', metadata_ref)
- self.assertIn(self.role_admin['id'], metadata_ref['roles'])
- def test_authenticate_no_metadata(self):
+ def test_authenticate_and_get_roles_no_metadata(self):
user = {
'id': 'no_meta',
'name': 'NO_META',
@@ -126,18 +91,18 @@ class IdentityTests(object):
self.identity_api.create_user(user['id'], user)
self.identity_api.add_user_to_project(self.tenant_baz['id'],
user['id'])
- user_ref, tenant_ref, metadata_ref = self.identity_api.authenticate(
+ user_ref = self.identity_api.authenticate(
user_id=user['id'],
- tenant_id=self.tenant_baz['id'],
password=user['password'])
# NOTE(termie): the password field is left in user_foo to make
# it easier to authenticate in tests, but should
# not be returned by the api
user.pop('password')
- self.assertEquals(metadata_ref, {"roles":
- [CONF.member_role_id]})
self.assertDictContainsSubset(user, user_ref)
- self.assertDictEqual(tenant_ref, self.tenant_baz)
+ role_list = self.identity_api.get_roles_for_user_and_project(
+ user['id'], self.tenant_baz['id'])
+ self.assertEqual(len(role_list), 1)
+ self.assertIn(CONF.member_role_id, role_list)
def test_password_hashed(self):
user_ref = self.identity_api._get_user(self.user_foo['id'])
@@ -153,26 +118,25 @@ class IdentityTests(object):
self.assertEqual(unicode_name, ref['name'])
def test_get_project(self):
- tenant_ref = self.identity_api.get_project(
- tenant_id=self.tenant_bar['id'])
+ tenant_ref = self.identity_api.get_project(self.tenant_bar['id'])
self.assertDictEqual(tenant_ref, self.tenant_bar)
def test_get_project_404(self):
self.assertRaises(exception.ProjectNotFound,
self.identity_api.get_project,
- tenant_id=uuid.uuid4().hex)
+ uuid.uuid4().hex)
def test_get_project_by_name(self):
tenant_ref = self.identity_api.get_project_by_name(
- tenant_name=self.tenant_bar['name'],
- domain_id=DEFAULT_DOMAIN_ID)
+ self.tenant_bar['name'],
+ DEFAULT_DOMAIN_ID)
self.assertDictEqual(tenant_ref, self.tenant_bar)
def test_get_project_by_name_404(self):
self.assertRaises(exception.ProjectNotFound,
self.identity_api.get_project_by_name,
- tenant_name=uuid.uuid4().hex,
- domain_id=DEFAULT_DOMAIN_ID)
+ uuid.uuid4().hex,
+ DEFAULT_DOMAIN_ID)
def test_get_project_users(self):
tenant_ref = self.identity_api.get_project_users(self.tenant_baz['id'])
@@ -187,10 +151,10 @@ class IdentityTests(object):
def test_get_project_users_404(self):
self.assertRaises(exception.ProjectNotFound,
self.identity_api.get_project_users,
- tenant_id=uuid.uuid4().hex)
+ uuid.uuid4().hex)
def test_get_user(self):
- user_ref = self.identity_api.get_user(user_id=self.user_foo['id'])
+ user_ref = self.identity_api.get_user(self.user_foo['id'])
# NOTE(termie): the password field is left in user_foo to make
# it easier to authenticate in tests, but should
# not be returned by the api
@@ -200,12 +164,12 @@ class IdentityTests(object):
def test_get_user_404(self):
self.assertRaises(exception.UserNotFound,
self.identity_api.get_user,
- user_id=uuid.uuid4().hex)
+ uuid.uuid4().hex)
def test_get_user_by_name(self):
user_ref = self.identity_api.get_user_by_name(
- user_name=self.user_foo['name'],
- domain_id=DEFAULT_DOMAIN_ID)
+ self.user_foo['name'], DEFAULT_DOMAIN_ID)
+
# NOTE(termie): the password field is left in user_foo to make
# it easier to authenticate in tests, but should
# not be returned by the api
@@ -215,38 +179,18 @@ class IdentityTests(object):
def test_get_user_by_name_404(self):
self.assertRaises(exception.UserNotFound,
self.identity_api.get_user_by_name,
- user_name=uuid.uuid4().hex,
- domain_id=DEFAULT_DOMAIN_ID)
-
- def test_get_metadata(self):
- metadata_ref = self.identity_api.get_metadata(
- user_id=self.user_sna['id'],
- tenant_id=self.tenant_bar['id'])
- metadata_ref.pop('roles')
- self.assertDictEqual(metadata_ref, self.metadata_snamtu)
-
- def test_get_metadata_404(self):
- # FIXME(dolph): these exceptions could be more specific
- self.assertRaises(exception.NotFound,
- self.identity_api.get_metadata,
- user_id=uuid.uuid4().hex,
- tenant_id=self.tenant_bar['id'])
-
- self.assertRaises(exception.NotFound,
- self.identity_api.get_metadata,
- user_id=self.user_foo['id'],
- tenant_id=uuid.uuid4().hex)
+ uuid.uuid4().hex,
+ DEFAULT_DOMAIN_ID)
def test_get_role(self):
- role_ref = self.identity_api.get_role(
- role_id=self.role_admin['id'])
+ role_ref = self.identity_api.get_role(self.role_admin['id'])
role_ref_dict = dict((x, role_ref[x]) for x in role_ref)
self.assertDictEqual(role_ref_dict, self.role_admin)
def test_get_role_404(self):
self.assertRaises(exception.RoleNotFound,
self.identity_api.get_role,
- role_id=uuid.uuid4().hex)
+ uuid.uuid4().hex)
def test_create_duplicate_role_name_fails(self):
role = {'id': 'fake1',
@@ -482,6 +426,72 @@ class IdentityTests(object):
self.identity_api.get_project,
'fake2')
+ def test_list_role_assignments_unfiltered(self):
+ """Test for unfiltered listing role assignments.
+
+ Test Plan:
+ - Create a domain, with a user, group & project
+ - Find how many role assignments already exist (from default
+ fixtures)
+ - Create a grant of each type (user/group on project/domain)
+ - Check the number of assignments has gone up by 4 and that
+ the entries we added are in the list returned
+
+ """
+ new_domain = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex}
+ self.identity_api.create_domain(new_domain['id'], new_domain)
+ new_user = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex,
+ 'password': uuid.uuid4().hex, 'enabled': True,
+ 'domain_id': new_domain['id']}
+ self.identity_api.create_user(new_user['id'],
+ new_user)
+ new_group = {'id': uuid.uuid4().hex, 'domain_id': new_domain['id'],
+ 'name': uuid.uuid4().hex}
+ self.identity_api.create_group(new_group['id'], new_group)
+ new_project = {'id': uuid.uuid4().hex,
+ 'name': uuid.uuid4().hex,
+ 'domain_id': new_domain['id']}
+ self.identity_api.create_project(new_project['id'], new_project)
+
+ # First check how many role grant already exist
+ existing_assignments = len(self.identity_api.list_role_assignments())
+
+ # Now create the grants (roles are defined in default_fixtures)
+ self.identity_api.create_grant(user_id=new_user['id'],
+ domain_id=new_domain['id'],
+ role_id='member')
+ self.identity_api.create_grant(user_id=new_user['id'],
+ project_id=new_project['id'],
+ role_id='other')
+ self.identity_api.create_grant(group_id=new_group['id'],
+ domain_id=new_domain['id'],
+ role_id='admin')
+ self.identity_api.create_grant(group_id=new_group['id'],
+ project_id=new_project['id'],
+ role_id='admin')
+
+ # Read back the list of assignments - check it is gone up by 4
+ assignment_list = self.identity_api.list_role_assignments()
+ self.assertEquals(len(assignment_list), existing_assignments + 4)
+
+ # Now check that each of our four new entries are in the list
+ self.assertIn(
+ {'user_id': new_user['id'], 'domain_id': new_domain['id'],
+ 'role_id': 'member'},
+ assignment_list)
+ self.assertIn(
+ {'user_id': new_user['id'], 'project_id': new_project['id'],
+ 'role_id': 'other'},
+ assignment_list)
+ self.assertIn(
+ {'group_id': new_group['id'], 'domain_id': new_domain['id'],
+ 'role_id': 'admin'},
+ assignment_list)
+ self.assertIn(
+ {'group_id': new_group['id'], 'project_id': new_project['id'],
+ 'role_id': 'admin'},
+ assignment_list)
+
def test_add_duplicate_role_grant(self):
roles_ref = self.identity_api.get_roles_for_user_and_project(
self.user_foo['id'], self.tenant_bar['id'])
@@ -658,7 +668,7 @@ class IdentityTests(object):
project_id=self.tenant_bar['id'])
roles_ref_ids = []
- for i, ref in enumerate(roles_ref):
+ for ref in roles_ref:
roles_ref_ids.append(ref['id'])
self.assertIn(self.role_admin['id'], roles_ref_ids)
self.assertIn('member', roles_ref_ids)
@@ -1065,7 +1075,7 @@ class IdentityTests(object):
project_id=project1['id'])
roles_ref_ids = []
- for i, ref in enumerate(roles_ref):
+ for ref in roles_ref:
roles_ref_ids.append(ref['id'])
self.assertIn(role1['id'], roles_ref_ids)
self.assertIn(role2['id'], roles_ref_ids)
@@ -1081,7 +1091,7 @@ class IdentityTests(object):
def test_multi_role_grant_by_user_group_on_project_domain(self):
role_list = []
- for _ in range(8):
+ for _ in range(10):
role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex}
self.identity_api.create_role(role['id'], role)
role_list.append(role)
@@ -1094,12 +1104,17 @@ class IdentityTests(object):
group1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex,
'domain_id': domain1['id'], 'enabled': True}
self.identity_api.create_group(group1['id'], group1)
+ group2 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex,
+ 'domain_id': domain1['id'], 'enabled': True}
+ self.identity_api.create_group(group2['id'], group2)
project1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex,
'domain_id': domain1['id']}
self.identity_api.create_project(project1['id'], project1)
self.identity_api.add_user_to_group(user1['id'],
group1['id'])
+ self.identity_api.add_user_to_group(user1['id'],
+ group2['id'])
roles_ref = self.identity_api.list_grants(
user_id=user1['id'],
@@ -1150,6 +1165,105 @@ class IdentityTests(object):
self.assertIn(role_list[6], roles_ref)
self.assertIn(role_list[7], roles_ref)
+ # Now test the alternate way of getting back lists of grants,
+ # where user and group roles are combined. These should match
+ # the above results.
+ combined_role_list = self.identity_api.get_roles_for_user_and_project(
+ user1['id'], project1['id'])
+ self.assertEquals(len(combined_role_list), 4)
+ self.assertIn(role_list[4]['id'], combined_role_list)
+ self.assertIn(role_list[5]['id'], combined_role_list)
+ self.assertIn(role_list[6]['id'], combined_role_list)
+ self.assertIn(role_list[7]['id'], combined_role_list)
+
+ combined_role_list = self.identity_api.get_roles_for_user_and_domain(
+ user1['id'], domain1['id'])
+ self.assertEquals(len(combined_role_list), 4)
+ self.assertIn(role_list[0]['id'], combined_role_list)
+ self.assertIn(role_list[1]['id'], combined_role_list)
+ self.assertIn(role_list[2]['id'], combined_role_list)
+ self.assertIn(role_list[3]['id'], combined_role_list)
+
+ def test_multi_group_grants_on_project_domain(self):
+ """Test multiple group roles for user on project and domain.
+
+ Test Plan:
+ - Create 6 roles
+ - Create a domain, with a project, user and two groups
+ - Make the user a member of both groups
+ - Check no roles yet exit
+ - Assign a role to each user and both groups on both the
+ project and domain
+ - Get a list of effective roles for the user on both the
+ project and domain, checking we get back the correct three
+ roles
+
+ """
+ role_list = []
+ for _ in range(6):
+ role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex}
+ self.identity_api.create_role(role['id'], role)
+ role_list.append(role)
+ domain1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex}
+ self.identity_api.create_domain(domain1['id'], domain1)
+ user1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex,
+ 'domain_id': domain1['id'], 'password': uuid.uuid4().hex,
+ 'enabled': True}
+ self.identity_api.create_user(user1['id'], user1)
+ group1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex,
+ 'domain_id': domain1['id'], 'enabled': True}
+ self.identity_api.create_group(group1['id'], group1)
+ group2 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex,
+ 'domain_id': domain1['id'], 'enabled': True}
+ self.identity_api.create_group(group2['id'], group2)
+ project1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex,
+ 'domain_id': domain1['id']}
+ self.identity_api.create_project(project1['id'], project1)
+
+ self.identity_api.add_user_to_group(user1['id'],
+ group1['id'])
+ self.identity_api.add_user_to_group(user1['id'],
+ group2['id'])
+
+ roles_ref = self.identity_api.list_grants(
+ user_id=user1['id'],
+ project_id=project1['id'])
+ self.assertEquals(len(roles_ref), 0)
+ self.identity_api.create_grant(user_id=user1['id'],
+ domain_id=domain1['id'],
+ role_id=role_list[0]['id'])
+ self.identity_api.create_grant(group_id=group1['id'],
+ domain_id=domain1['id'],
+ role_id=role_list[1]['id'])
+ self.identity_api.create_grant(group_id=group2['id'],
+ domain_id=domain1['id'],
+ role_id=role_list[2]['id'])
+ self.identity_api.create_grant(user_id=user1['id'],
+ project_id=project1['id'],
+ role_id=role_list[3]['id'])
+ self.identity_api.create_grant(group_id=group1['id'],
+ project_id=project1['id'],
+ role_id=role_list[4]['id'])
+ self.identity_api.create_grant(group_id=group2['id'],
+ project_id=project1['id'],
+ role_id=role_list[5]['id'])
+
+ # Read by the roles, ensuring we get the correct 3 roles for
+ # both project and domain
+ combined_role_list = self.identity_api.get_roles_for_user_and_project(
+ user1['id'], project1['id'])
+ self.assertEquals(len(combined_role_list), 3)
+ self.assertIn(role_list[3]['id'], combined_role_list)
+ self.assertIn(role_list[4]['id'], combined_role_list)
+ self.assertIn(role_list[5]['id'], combined_role_list)
+
+ combined_role_list = self.identity_api.get_roles_for_user_and_domain(
+ user1['id'], domain1['id'])
+ self.assertEquals(len(combined_role_list), 3)
+ self.assertIn(role_list[0]['id'], combined_role_list)
+ self.assertIn(role_list[1]['id'], combined_role_list)
+ self.assertIn(role_list[2]['id'], combined_role_list)
+
def test_delete_role_with_user_and_group_grants(self):
role1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex}
self.identity_api.create_role(role1['id'], role1)
@@ -1655,6 +1769,30 @@ class IdentityTests(object):
self.assertIn(self.tenant_bar['id'], project_ids)
self.assertIn(self.tenant_baz['id'], project_ids)
+ def test_list_projects_for_domain(self):
+ project_ids = ([x['id'] for x in
+ self.assignment_api.list_projects(DEFAULT_DOMAIN_ID)])
+ self.assertEquals(len(project_ids), 4)
+ self.assertIn(self.tenant_bar['id'], project_ids)
+ self.assertIn(self.tenant_baz['id'], project_ids)
+ self.assertIn(self.tenant_mtu['id'], project_ids)
+ self.assertIn(self.tenant_service['id'], project_ids)
+
+ def test_list_projects_for_alternate_domain(self):
+ domain1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex}
+ self.assignment_api.create_domain(domain1['id'], domain1)
+ project1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex,
+ 'domain_id': domain1['id']}
+ self.assignment_api.create_project(project1['id'], project1)
+ project2 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex,
+ 'domain_id': domain1['id']}
+ self.assignment_api.create_project(project2['id'], project2)
+ project_ids = ([x['id'] for x in
+ self.assignment_api.list_projects(domain1['id'])])
+ self.assertEquals(len(project_ids), 2)
+ self.assertIn(project1['id'], project_ids)
+ self.assertIn(project2['id'], project_ids)
+
def test_list_roles(self):
roles = self.identity_api.list_roles()
for test_role in default_fixtures.ROLES:
@@ -2353,7 +2491,7 @@ class TrustTests(object):
{'id': 'browser'}], trust_data['roles'])
def test_list_trust_by_trustee(self):
- for i in range(0, 3):
+ for i in range(3):
self.create_sample_trust(uuid.uuid4().hex)
trusts = self.trust_api.list_trusts_for_trustee(self.trustee['id'])
self.assertEqual(len(trusts), 3)
@@ -2362,7 +2500,7 @@ class TrustTests(object):
self.assertEqual(len(trusts), 0)
def test_list_trust_by_trustor(self):
- for i in range(0, 3):
+ for i in range(3):
self.create_sample_trust(uuid.uuid4().hex)
trusts = self.trust_api.list_trusts_for_trustor(self.trustor['id'])
self.assertEqual(len(trusts), 3)
@@ -2371,7 +2509,7 @@ class TrustTests(object):
self.assertEqual(len(trusts), 0)
def test_list_trusts(self):
- for i in range(0, 3):
+ for i in range(3):
self.create_sample_trust(uuid.uuid4().hex)
trusts = self.trust_api.list_trusts()
self.assertEqual(len(trusts), 3)
@@ -2579,3 +2717,164 @@ class PolicyTests(object):
self.assertRaises(exception.PolicyNotFound,
self.policy_api.delete_policy,
uuid.uuid4().hex)
+
+
+class InheritanceTests(object):
+
+ def test_inherited_role_grants_for_user(self):
+ """Test inherited user roles.
+
+ Test Plan:
+ - Enable OS-INHERIT extension
+ - Create 3 roles
+ - Create a domain, with a project and a user
+ - Check no roles yet exit
+ - Assign a direct user role to the project and a (non-inherited)
+ user role to the domain
+ - Get a list of effective roles - should only get the one direct role
+ - Now add an inherited user role to the domain
+ - Get a list of effective roles - should have two roles, one
+ direct and one by virtue of the inherited user role
+ - Also get effective roles for the domain - the role marked as
+ inherited should not show up
+
+ """
+ self.opt_in_group('os_inherit', enabled=True)
+ role_list = []
+ for _ in range(3):
+ role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex}
+ self.identity_api.create_role(role['id'], role)
+ role_list.append(role)
+ domain1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex}
+ self.identity_api.create_domain(domain1['id'], domain1)
+ user1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex,
+ 'domain_id': domain1['id'], 'password': uuid.uuid4().hex,
+ 'enabled': True}
+ self.identity_api.create_user(user1['id'], user1)
+ project1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex,
+ 'domain_id': domain1['id']}
+ self.identity_api.create_project(project1['id'], project1)
+
+ roles_ref = self.identity_api.list_grants(
+ user_id=user1['id'],
+ project_id=project1['id'])
+ self.assertEquals(len(roles_ref), 0)
+
+ # Create the first two roles - the domain one is not inherited
+ self.identity_api.create_grant(user_id=user1['id'],
+ project_id=project1['id'],
+ role_id=role_list[0]['id'])
+ self.identity_api.create_grant(user_id=user1['id'],
+ domain_id=domain1['id'],
+ role_id=role_list[1]['id'])
+
+ # Now get the effective roles for the user and project, this
+ # should only include the direct role assignment on the project
+ combined_role_list = self.identity_api.get_roles_for_user_and_project(
+ user1['id'], project1['id'])
+ self.assertEquals(len(combined_role_list), 1)
+ self.assertIn(role_list[0]['id'], combined_role_list)
+
+ # Now add an inherited role on the domain
+ self.identity_api.create_grant(user_id=user1['id'],
+ domain_id=domain1['id'],
+ role_id=role_list[2]['id'],
+ inherited_to_projects=True)
+
+ # Now get the effective roles for the user and project again, this
+ # should now include the inherited role on the domain
+ combined_role_list = self.identity_api.get_roles_for_user_and_project(
+ user1['id'], project1['id'])
+ self.assertEquals(len(combined_role_list), 2)
+ self.assertIn(role_list[0]['id'], combined_role_list)
+ self.assertIn(role_list[2]['id'], combined_role_list)
+
+ # Finally, check that the inherited role does not appear as a valid
+ # directly assigned role on the domain itself
+ combined_role_list = self.identity_api.get_roles_for_user_and_domain(
+ user1['id'], domain1['id'])
+ self.assertEquals(len(combined_role_list), 1)
+ self.assertIn(role_list[1]['id'], combined_role_list)
+
+ def test_inherited_role_grants_for_group(self):
+ """Test inherited group roles.
+
+ Test Plan:
+ - Enable OS-INHERIT extension
+ - Create 4 roles
+ - Create a domain, with a project, user and two groups
+ - Make the user a member of both groups
+ - Check no roles yet exit
+ - Assign a direct user role to the project and a (non-inherited)
+ group role on the domain
+ - Get a list of effective roles - should only get the one direct role
+ - Now add two inherited group roles to the domain
+ - Get a list of effective roles - should have three roles, one
+ direct and two by virtue of inherited group roles
+
+ """
+ self.opt_in_group('os_inherit', enabled=True)
+ role_list = []
+ for _ in range(4):
+ role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex}
+ self.identity_api.create_role(role['id'], role)
+ role_list.append(role)
+ domain1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex}
+ self.identity_api.create_domain(domain1['id'], domain1)
+ user1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex,
+ 'domain_id': domain1['id'], 'password': uuid.uuid4().hex,
+ 'enabled': True}
+ self.identity_api.create_user(user1['id'], user1)
+ group1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex,
+ 'domain_id': domain1['id'], 'enabled': True}
+ self.identity_api.create_group(group1['id'], group1)
+ group2 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex,
+ 'domain_id': domain1['id'], 'enabled': True}
+ self.identity_api.create_group(group2['id'], group2)
+ project1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex,
+ 'domain_id': domain1['id']}
+ self.identity_api.create_project(project1['id'], project1)
+
+ self.identity_api.add_user_to_group(user1['id'],
+ group1['id'])
+ self.identity_api.add_user_to_group(user1['id'],
+ group2['id'])
+
+ roles_ref = self.identity_api.list_grants(
+ user_id=user1['id'],
+ project_id=project1['id'])
+ self.assertEquals(len(roles_ref), 0)
+
+ # Create two roles - the domain one is not inherited
+ self.identity_api.create_grant(user_id=user1['id'],
+ project_id=project1['id'],
+ role_id=role_list[0]['id'])
+ self.identity_api.create_grant(group_id=group1['id'],
+ domain_id=domain1['id'],
+ role_id=role_list[1]['id'])
+
+ # Now get the effective roles for the user and project, this
+ # should only include the direct role assignment on the project
+ combined_role_list = self.identity_api.get_roles_for_user_and_project(
+ user1['id'], project1['id'])
+ self.assertEquals(len(combined_role_list), 1)
+ self.assertIn(role_list[0]['id'], combined_role_list)
+
+ # Now add to more group roles, both inherited, to the domain
+ self.identity_api.create_grant(group_id=group2['id'],
+ domain_id=domain1['id'],
+ role_id=role_list[2]['id'],
+ inherited_to_projects=True)
+ self.identity_api.create_grant(group_id=group2['id'],
+ domain_id=domain1['id'],
+ role_id=role_list[3]['id'],
+ inherited_to_projects=True)
+
+ # Now get the effective roles for the user and project again, this
+ # should now include the inherited roles on the domain
+ combined_role_list = self.identity_api.get_roles_for_user_and_project(
+ user1['id'], project1['id'])
+ self.assertEquals(len(combined_role_list), 3)
+ self.assertIn(role_list[0]['id'], combined_role_list)
+ self.assertIn(role_list[2]['id'], combined_role_list)
+ self.assertIn(role_list[3]['id'], combined_role_list)
diff --git a/tests/test_backend_kvs.py b/tests/test_backend_kvs.py
index 0c6c2abe..d92a7510 100644
--- a/tests/test_backend_kvs.py
+++ b/tests/test_backend_kvs.py
@@ -15,8 +15,6 @@
# under the License.
import uuid
-import nose.exc
-
from keystone import test
from keystone import exception
@@ -36,34 +34,34 @@ class KvsIdentity(test.TestCase, test_backend.IdentityTests):
def test_list_user_projects(self):
# NOTE(chungg): not implemented
- raise nose.exc.SkipTest('Blocked by bug 1119770')
+ self.skipTest('Blocked by bug 1119770')
def test_create_duplicate_group_name_in_different_domains(self):
- raise nose.exc.SkipTest('Blocked by bug 1119770')
+ self.skipTest('Blocked by bug 1119770')
def test_create_duplicate_user_name_in_different_domains(self):
- raise nose.exc.SkipTest('Blocked by bug 1119770')
+ self.skipTest('Blocked by bug 1119770')
def test_create_duplicate_project_name_in_different_domains(self):
- raise nose.exc.SkipTest('Blocked by bug 1119770')
+ self.skipTest('Blocked by bug 1119770')
def test_move_user_between_domains(self):
- raise nose.exc.SkipTest('Blocked by bug 1119770')
+ self.skipTest('Blocked by bug 1119770')
def test_move_user_between_domains_with_clashing_names_fails(self):
- raise nose.exc.SkipTest('Blocked by bug 1119770')
+ self.skipTest('Blocked by bug 1119770')
def test_move_group_between_domains(self):
- raise nose.exc.SkipTest('Blocked by bug 1119770')
+ self.skipTest('Blocked by bug 1119770')
def test_move_group_between_domains_with_clashing_names_fails(self):
- raise nose.exc.SkipTest('Blocked by bug 1119770')
+ self.skipTest('Blocked by bug 1119770')
def test_move_project_between_domains(self):
- raise nose.exc.SkipTest('Blocked by bug 1119770')
+ self.skipTest('Blocked by bug 1119770')
def test_move_project_between_domains_with_clashing_names_fails(self):
- raise nose.exc.SkipTest('Blocked by bug 1119770')
+ self.skipTest('Blocked by bug 1119770')
class KvsToken(test.TestCase, test_backend.TokenTests):
diff --git a/tests/test_backend_ldap.py b/tests/test_backend_ldap.py
index 577a6ef0..ec2b2737 100644
--- a/tests/test_backend_ldap.py
+++ b/tests/test_backend_ldap.py
@@ -17,14 +17,13 @@
import uuid
-import nose.exc
-
-from keystone import test
-
+from keystone import assignment
from keystone.common.ldap import fakeldap
+from keystone.common import sql
from keystone import config
from keystone import exception
from keystone import identity
+from keystone import test
import default_fixtures
import test_backend
@@ -33,7 +32,7 @@ import test_backend
CONF = config.CONF
-class LDAPIdentity(test.TestCase, test_backend.IdentityTests):
+class BaseLDAPIdentity(test_backend.IdentityTests):
def _get_domain_fixture(self):
"""Domains in LDAP are read-only, so just return the static one."""
return self.identity_api.get_domain(CONF.identity.default_domain_id)
@@ -47,14 +46,6 @@ class LDAPIdentity(test.TestCase, test_backend.IdentityTests):
test.testsdir('test_overrides.conf'),
test.testsdir('backend_ldap.conf')])
- def setUp(self):
- super(LDAPIdentity, self).setUp()
- self._set_config()
- self.clear_database()
-
- self.load_backends()
- self.load_fixtures(default_fixtures)
-
def test_build_tree(self):
"""Regression test for building the tree names
"""
@@ -104,6 +95,202 @@ class LDAPIdentity(test.TestCase, test_backend.IdentityTests):
self.identity_api.delete_user,
self.user_foo['id'])
+ def test_user_filter(self):
+ user_ref = self.identity_api.get_user(self.user_foo['id'])
+ self.user_foo.pop('password')
+ self.assertDictEqual(user_ref, self.user_foo)
+
+ CONF.ldap.user_filter = '(CN=DOES_NOT_MATCH)'
+ self.load_backends()
+ self.assertRaises(exception.UserNotFound,
+ self.identity_api.get_user,
+ self.user_foo['id'])
+
+ def test_get_role_grant_by_user_and_project(self):
+ self.skipTest('Blocked by bug 1101287')
+
+ def test_get_role_grants_for_user_and_project_404(self):
+ self.skipTest('Blocked by bug 1101287')
+
+ def test_add_role_grant_to_user_and_project_404(self):
+ self.skipTest('Blocked by bug 1101287')
+
+ def test_remove_role_grant_from_user_and_project(self):
+ self.skipTest('Blocked by bug 1101287')
+
+ def test_get_and_remove_role_grant_by_group_and_project(self):
+ self.skipTest('Blocked by bug 1101287')
+
+ def test_get_and_remove_role_grant_by_group_and_domain(self):
+ self.skipTest('N/A: LDAP does not support multiple domains')
+
+ def test_get_and_remove_role_grant_by_user_and_domain(self):
+ self.skipTest('N/A: LDAP does not support multiple domains')
+
+ def test_get_and_remove_correct_role_grant_from_a_mix(self):
+ self.skipTest('Blocked by bug 1101287')
+
+ def test_get_and_remove_role_grant_by_group_and_cross_domain(self):
+ self.skipTest('N/A: LDAP does not support multiple domains')
+
+ def test_get_and_remove_role_grant_by_user_and_cross_domain(self):
+ self.skipTest('N/A: LDAP does not support multiple domains')
+
+ def test_role_grant_by_group_and_cross_domain_project(self):
+ self.skipTest('N/A: LDAP does not support multiple domains')
+
+ def test_role_grant_by_user_and_cross_domain_project(self):
+ self.skipTest('N/A: LDAP does not support multiple domains')
+
+ def test_multi_role_grant_by_user_group_on_project_domain(self):
+ self.skipTest('N/A: LDAP does not support multiple domains')
+
+ def test_delete_role_with_user_and_group_grants(self):
+ self.skipTest('Blocked by bug 1101287')
+
+ def test_delete_user_with_group_project_domain_links(self):
+ self.skipTest('N/A: LDAP does not support multiple domains')
+
+ def test_delete_group_with_user_project_domain_links(self):
+ self.skipTest('N/A: LDAP does not support multiple domains')
+
+ def test_list_user_projects(self):
+ self.skipTest('Blocked by bug 1101287')
+
+ def test_create_duplicate_user_name_in_different_domains(self):
+ self.skipTest('Blocked by bug 1101276')
+
+ def test_create_duplicate_project_name_in_different_domains(self):
+ self.skipTest('Blocked by bug 1101276')
+
+ def test_create_duplicate_group_name_in_different_domains(self):
+ self.skipTest(
+ 'N/A: LDAP does not support multiple domains')
+
+ def test_move_user_between_domains(self):
+ self.skipTest('Blocked by bug 1101276')
+
+ def test_move_user_between_domains_with_clashing_names_fails(self):
+ self.skipTest('Blocked by bug 1101276')
+
+ def test_move_group_between_domains(self):
+ self.skipTest(
+ 'N/A: LDAP does not support multiple domains')
+
+ def test_move_group_between_domains_with_clashing_names_fails(self):
+ self.skipTest('Blocked by bug 1101276')
+
+ def test_move_project_between_domains(self):
+ self.skipTest('Blocked by bug 1101276')
+
+ def test_move_project_between_domains_with_clashing_names_fails(self):
+ self.skipTest('Blocked by bug 1101276')
+
+ def test_get_roles_for_user_and_domain(self):
+ self.skipTest('N/A: LDAP does not support multiple domains')
+
+ def test_list_role_assignments_unfiltered(self):
+ self.skipTest('Blocked by bug 1195019')
+
+ def test_multi_group_grants_on_project_domain(self):
+ self.skipTest('Blocked by bug 1101287')
+
+ def test_list_group_members_missing_entry(self):
+ """List group members with deleted user.
+
+ If a group has a deleted entry for a member, the non-deleted members
+ are returned.
+
+ """
+
+ # Create a group
+ group_id = None
+ group = dict(name=uuid.uuid4().hex)
+ group_id = self.identity_api.create_group(group_id, group)['id']
+
+ # Create a couple of users and add them to the group.
+ user_id = None
+ user = dict(name=uuid.uuid4().hex, id=uuid.uuid4().hex)
+ user_1_id = self.identity_api.create_user(user_id, user)['id']
+
+ self.identity_api.add_user_to_group(user_1_id, group_id)
+
+ user_id = None
+ user = dict(name=uuid.uuid4().hex, id=uuid.uuid4().hex)
+ user_2_id = self.identity_api.create_user(user_id, user)['id']
+
+ self.identity_api.add_user_to_group(user_2_id, group_id)
+
+ # Delete user 2
+ # NOTE(blk-u): need to go directly to user interface to keep from
+ # updating the group.
+ self.identity_api.driver.user.delete(user_2_id)
+
+ # List group users and verify only user 1.
+ res = self.identity_api.list_users_in_group(group_id)
+
+ self.assertEqual(len(res), 1, "Expected 1 entry (user_1)")
+ self.assertEqual(res[0]['id'], user_1_id, "Expected user 1 id")
+
+ def test_list_domains(self):
+ domains = self.identity_api.list_domains()
+ self.assertEquals(
+ domains,
+ [assignment.DEFAULT_DOMAIN])
+
+ def test_authenticate_requires_simple_bind(self):
+ user = {
+ 'id': 'no_meta',
+ 'name': 'NO_META',
+ 'domain_id': test_backend.DEFAULT_DOMAIN_ID,
+ 'password': 'no_meta2',
+ 'enabled': True,
+ }
+ self.identity_api.create_user(user['id'], user)
+ self.identity_api.add_user_to_project(self.tenant_baz['id'],
+ user['id'])
+ self.identity_api.driver.user.LDAP_USER = None
+ self.identity_api.driver.user.LDAP_PASSWORD = None
+
+ self.assertRaises(AssertionError,
+ self.identity_api.authenticate,
+ user_id=user['id'],
+ password=None)
+
+ # (spzala)The group and domain crud tests below override the standard ones
+ # in test_backend.py so that we can exclude the update name test, since we
+ # do not yet support the update of either group or domain names with LDAP.
+ # In the tests below, the update is demonstrated by updating description.
+ # Refer to bug 1136403 for more detail.
+ def test_group_crud(self):
+ group = {
+ 'id': uuid.uuid4().hex,
+ 'domain_id': CONF.identity.default_domain_id,
+ 'name': uuid.uuid4().hex,
+ 'description': uuid.uuid4().hex}
+ self.identity_api.create_group(group['id'], group)
+ group_ref = self.identity_api.get_group(group['id'])
+ self.assertDictEqual(group_ref, group)
+ group['description'] = uuid.uuid4().hex
+ self.identity_api.update_group(group['id'], group)
+ group_ref = self.identity_api.get_group(group['id'])
+ self.assertDictEqual(group_ref, group)
+
+ self.identity_api.delete_group(group['id'])
+ self.assertRaises(exception.GroupNotFound,
+ self.identity_api.get_group,
+ group['id'])
+
+
+class LDAPIdentity(test.TestCase, BaseLDAPIdentity):
+ def setUp(self):
+ super(LDAPIdentity, self).setUp()
+ self._set_config()
+ self.clear_database()
+
+ self.load_backends()
+ self.load_fixtures(default_fixtures)
+
def test_configurable_allowed_project_actions(self):
tenant = {'id': 'fake1', 'name': 'fake1', 'enabled': True}
self.identity_api.create_project('fake1', tenant)
@@ -175,17 +362,6 @@ class LDAPIdentity(test.TestCase, test_backend.IdentityTests):
self.identity_api.delete_role,
self.role_member['id'])
- def test_user_filter(self):
- user_ref = self.identity_api.get_user(self.user_foo['id'])
- self.user_foo.pop('password')
- self.assertDictEqual(user_ref, self.user_foo)
-
- CONF.ldap.user_filter = '(CN=DOES_NOT_MATCH)'
- self.load_backends()
- self.assertRaises(exception.UserNotFound,
- self.identity_api.get_user,
- self.user_foo['id'])
-
def test_project_filter(self):
tenant_ref = self.identity_api.get_project(self.tenant_bar['id'])
self.assertDictEqual(tenant_ref, self.tenant_bar)
@@ -216,40 +392,6 @@ class LDAPIdentity(test.TestCase, test_backend.IdentityTests):
self.identity_api.get_user,
'dumb')
- def test_user_attribute_mapping(self):
- CONF.ldap.user_name_attribute = 'sn'
- CONF.ldap.user_mail_attribute = 'mail'
- CONF.ldap.user_enabled_attribute = 'enabled'
- self.clear_database()
- self.load_backends()
- self.load_fixtures(default_fixtures)
- user_ref = self.identity_api.get_user(self.user_two['id'])
- self.assertEqual(user_ref['id'], self.user_two['id'])
- self.assertEqual(user_ref['name'], self.user_two['name'])
- self.assertEqual(user_ref['email'], self.user_two['email'])
-
- CONF.ldap.user_name_attribute = 'mail'
- CONF.ldap.user_mail_attribute = 'sn'
- self.load_backends()
- user_ref = self.identity_api.get_user(self.user_two['id'])
- self.assertEqual(user_ref['id'], self.user_two['id'])
- self.assertEqual(user_ref['name'], self.user_two['email'])
- self.assertEqual(user_ref['email'], self.user_two['name'])
-
- def test_user_attribute_ignore(self):
- CONF.ldap.user_attribute_ignore = ['email', 'password',
- 'tenant_id', 'enabled', 'tenants']
- self.clear_database()
- self.load_backends()
- self.load_fixtures(default_fixtures)
- user_ref = self.identity_api.get_user(self.user_two['id'])
- self.assertEqual(user_ref['id'], self.user_two['id'])
- self.assertNotIn('email', user_ref)
- self.assertNotIn('password', user_ref)
- self.assertNotIn('tenant_id', user_ref)
- self.assertNotIn('enabled', user_ref)
- self.assertNotIn('tenants', user_ref)
-
def test_project_attribute_mapping(self):
CONF.ldap.tenant_name_attribute = 'ou'
CONF.ldap.tenant_desc_attribute = 'description'
@@ -384,30 +526,6 @@ class LDAPIdentity(test.TestCase, test_backend.IdentityTests):
# TODO(henry-nash): These need to be removed when the full LDAP implementation
# is submitted - see Bugs 1092187, 1101287, 1101276, 1101289
- # (spzala)The group and domain crud tests below override the standard ones
- # in test_backend.py so that we can exclude the update name test, since we
- # do not yet support the update of either group or domain names with LDAP.
- # In the tests below, the update is demonstrated by updating description.
- # Refer to bug 1136403 for more detail.
- def test_group_crud(self):
- group = {
- 'id': uuid.uuid4().hex,
- 'domain_id': CONF.identity.default_domain_id,
- 'name': uuid.uuid4().hex,
- 'description': uuid.uuid4().hex}
- self.identity_api.create_group(group['id'], group)
- group_ref = self.identity_api.get_group(group['id'])
- self.assertDictEqual(group_ref, group)
- group['description'] = uuid.uuid4().hex
- self.identity_api.update_group(group['id'], group)
- group_ref = self.identity_api.get_group(group['id'])
- self.assertDictEqual(group_ref, group)
-
- self.identity_api.delete_group(group['id'])
- self.assertRaises(exception.GroupNotFound,
- self.identity_api.get_group,
- group['id'])
-
def test_domain_crud(self):
domain = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex,
'enabled': True, 'description': uuid.uuid4().hex}
@@ -434,30 +552,6 @@ class LDAPIdentity(test.TestCase, test_backend.IdentityTests):
self.identity_api.get_domain,
domain['id'])
- def test_get_role_grant_by_user_and_project(self):
- raise nose.exc.SkipTest('Blocked by bug 1101287')
-
- def test_get_role_grants_for_user_and_project_404(self):
- raise nose.exc.SkipTest('Blocked by bug 1101287')
-
- def test_add_role_grant_to_user_and_project_404(self):
- raise nose.exc.SkipTest('Blocked by bug 1101287')
-
- def test_remove_role_grant_from_user_and_project(self):
- raise nose.exc.SkipTest('Blocked by bug 1101287')
-
- def test_get_and_remove_role_grant_by_group_and_project(self):
- raise nose.exc.SkipTest('Blocked by bug 1101287')
-
- def test_get_and_remove_role_grant_by_group_and_domain(self):
- raise nose.exc.SkipTest('N/A: LDAP does not support multiple domains')
-
- def test_get_and_remove_role_grant_by_user_and_domain(self):
- raise nose.exc.SkipTest('N/A: LDAP does not support multiple domains')
-
- def test_get_and_remove_correct_role_grant_from_a_mix(self):
- raise nose.exc.SkipTest('Blocked by bug 1101287')
-
def test_project_crud(self):
# NOTE(topol): LDAP implementation does not currently support the
# updating of a project name so this method override
@@ -466,12 +560,12 @@ class LDAPIdentity(test.TestCase, test_backend.IdentityTests):
'domain_id': CONF.identity.default_domain_id,
'description': uuid.uuid4().hex
}
- self.identity_api.driver.create_project(project['id'], project)
- project_ref = self.identity_api.driver.get_project(project['id'])
+ self.assignment_api.create_project(project['id'], project)
+ project_ref = self.assignment_api.get_project(project['id'])
# NOTE(crazed): If running live test with emulation, there will be
# an enabled key in the project_ref.
- if self.identity_api.driver.project.enabled_emulation:
+ if self.assignment_api.driver.project.enabled_emulation:
project['enabled'] = True
self.assertDictEqual(project_ref, project)
@@ -485,129 +579,59 @@ class LDAPIdentity(test.TestCase, test_backend.IdentityTests):
self.identity_api.get_project,
project['id'])
- def test_get_and_remove_role_grant_by_group_and_cross_domain(self):
- raise nose.exc.SkipTest('N/A: LDAP does not support multiple domains')
-
- def test_get_and_remove_role_grant_by_user_and_cross_domain(self):
- raise nose.exc.SkipTest('N/A: LDAP does not support multiple domains')
-
- def test_role_grant_by_group_and_cross_domain_project(self):
- raise nose.exc.SkipTest('N/A: LDAP does not support multiple domains')
-
- def test_role_grant_by_user_and_cross_domain_project(self):
- raise nose.exc.SkipTest('N/A: LDAP does not support multiple domains')
-
def test_multi_role_grant_by_user_group_on_project_domain(self):
- raise nose.exc.SkipTest('N/A: LDAP does not support multiple domains')
-
- def test_delete_role_with_user_and_group_grants(self):
- raise nose.exc.SkipTest('Blocked by bug 1101287')
-
- def test_delete_user_with_group_project_domain_links(self):
- raise nose.exc.SkipTest('N/A: LDAP does not support multiple domains')
-
- def test_delete_group_with_user_project_domain_links(self):
- raise nose.exc.SkipTest('N/A: LDAP does not support multiple domains')
-
- def test_list_user_projects(self):
- raise nose.exc.SkipTest('Blocked by bug 1101287')
-
- def test_create_duplicate_user_name_in_different_domains(self):
- raise nose.exc.SkipTest('Blocked by bug 1101276')
-
- def test_create_duplicate_project_name_in_different_domains(self):
- raise nose.exc.SkipTest('Blocked by bug 1101276')
-
- def test_create_duplicate_group_name_in_different_domains(self):
- raise nose.exc.SkipTest(
- 'N/A: LDAP does not support multiple domains')
-
- def test_move_user_between_domains(self):
- raise nose.exc.SkipTest('Blocked by bug 1101276')
-
- def test_move_user_between_domains_with_clashing_names_fails(self):
- raise nose.exc.SkipTest('Blocked by bug 1101276')
-
- def test_move_group_between_domains(self):
- raise nose.exc.SkipTest(
+ # This is a partial implementation of the standard test that
+ # is defined in test_backend.py. It omits both domain and
+ # group grants. since neither of these are yet supported by
+ # the ldap backend.
+
+ role_list = []
+ for _ in range(2):
+ role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex}
+ self.identity_api.create_role(role['id'], role)
+ role_list.append(role)
+
+ user1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex,
+ 'domain_id': CONF.identity.default_domain_id,
+ 'password': uuid.uuid4().hex,
+ 'enabled': True}
+ self.identity_api.create_user(user1['id'], user1)
+ project1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex,
+ 'domain_id': CONF.identity.default_domain_id}
+ self.identity_api.create_project(project1['id'], project1)
+
+ self.identity_api.add_role_to_user_and_project(
+ user_id=user1['id'],
+ tenant_id=project1['id'],
+ role_id=role_list[0]['id'])
+ self.identity_api.add_role_to_user_and_project(
+ user_id=user1['id'],
+ tenant_id=project1['id'],
+ role_id=role_list[1]['id'])
+
+ # Although list_grants are not yet supported, we can test the
+ # alternate way of getting back lists of grants, where user
+ # and group roles are combined. Only directly assigned user
+ # roles are available, since group grants are not yet supported
+
+ combined_role_list = self.identity_api.get_roles_for_user_and_project(
+ user1['id'], project1['id'])
+ self.assertEquals(len(combined_role_list), 2)
+ self.assertIn(role_list[0]['id'], combined_role_list)
+ self.assertIn(role_list[1]['id'], combined_role_list)
+
+ # Finally, although domain roles are not implemented, check we can
+ # issue the combined get roles call with benign results, since thus is
+ # used in token generation
+
+ combined_role_list = self.identity_api.get_roles_for_user_and_domain(
+ user1['id'], CONF.identity.default_domain_id)
+ self.assertEquals(len(combined_role_list), 0)
+
+ def test_list_projects_for_alternate_domain(self):
+ self.skipTest(
'N/A: LDAP does not support multiple domains')
- def test_move_group_between_domains_with_clashing_names_fails(self):
- raise nose.exc.SkipTest('Blocked by bug 1101276')
-
- def test_move_project_between_domains(self):
- raise nose.exc.SkipTest('Blocked by bug 1101276')
-
- def test_move_project_between_domains_with_clashing_names_fails(self):
- raise nose.exc.SkipTest('Blocked by bug 1101276')
-
- def test_get_roles_for_user_and_domain(self):
- raise nose.exc.SkipTest('N/A: LDAP does not support multiple domains')
-
- def test_list_group_members_missing_entry(self):
- """List group members with deleted user.
-
- If a group has a deleted entry for a member, the non-deleted members
- are returned.
-
- """
-
- # Create a group
- group_id = None
- group = dict(name=uuid.uuid4().hex)
- group_id = self.identity_api.create_group(group_id, group)['id']
-
- # Create a couple of users and add them to the group.
- user_id = None
- user = dict(name=uuid.uuid4().hex, id=uuid.uuid4().hex)
- user_1_id = self.identity_api.create_user(user_id, user)['id']
-
- self.identity_api.add_user_to_group(user_1_id, group_id)
-
- user_id = None
- user = dict(name=uuid.uuid4().hex, id=uuid.uuid4().hex)
- user_2_id = self.identity_api.create_user(user_id, user)['id']
-
- self.identity_api.add_user_to_group(user_2_id, group_id)
-
- # Delete user 2
- # NOTE(blk-u): need to go directly to user interface to keep from
- # updating the group.
- self.identity_api.driver.user.delete(user_2_id)
-
- # List group users and verify only user 1.
- res = self.identity_api.list_users_in_group(group_id)
-
- self.assertEqual(len(res), 1, "Expected 1 entry (user_1)")
- self.assertEqual(res[0]['id'], user_1_id, "Expected user 1 id")
-
- def test_list_domains(self):
- domains = self.identity_api.list_domains()
- self.assertEquals(
- domains,
- [{'id': CONF.identity.default_domain_id,
- 'name': 'Default',
- 'enabled': True}])
-
- def test_authenticate_requires_simple_bind(self):
- user = {
- 'id': 'no_meta',
- 'name': 'NO_META',
- 'domain_id': test_backend.DEFAULT_DOMAIN_ID,
- 'password': 'no_meta2',
- 'enabled': True,
- }
- self.identity_api.create_user(user['id'], user)
- self.identity_api.add_user_to_project(self.tenant_baz['id'],
- user['id'])
- self.identity_api.driver.user.LDAP_USER = None
- self.identity_api.driver.user.LDAP_PASSWORD = None
-
- self.assertRaises(AssertionError,
- self.identity_api.authenticate_user,
- user_id=user['id'],
- password=None)
-
class LDAPIdentityEnabledEmulation(LDAPIdentity):
def setUp(self):
@@ -624,30 +648,6 @@ class LDAPIdentityEnabledEmulation(LDAPIdentity):
self.user_two, self.user_badguy]:
obj.setdefault('enabled', True)
- def test_authenticate_no_metadata(self):
- user = {
- 'id': 'no_meta',
- 'name': 'NO_META',
- 'domain_id': test_backend.DEFAULT_DOMAIN_ID,
- 'password': 'no_meta2',
- 'enabled': True,
- }
- self.identity_api.create_user(user['id'], user)
- self.identity_api.add_user_to_project(self.tenant_baz['id'],
- user['id'])
- user_ref, tenant_ref, metadata_ref = self.identity_api.authenticate(
- user_id=user['id'],
- tenant_id=self.tenant_baz['id'],
- password=user['password'])
- # NOTE(termie): the password field is left in user_foo to make
- # it easier to authenticate in tests, but should
- # not be returned by the api
- user.pop('password')
- self.assertEquals(metadata_ref, {"roles":
- [CONF.member_role_id]})
- self.assertDictEqual(user_ref, user)
- self.assertDictEqual(tenant_ref, self.tenant_baz)
-
def test_project_crud(self):
# NOTE(topol): LDAPIdentityEnabledEmulation will create an
# enabled key in the project dictionary so this
@@ -703,5 +703,43 @@ class LDAPIdentityEnabledEmulation(LDAPIdentity):
user['id'])
def test_user_enable_attribute_mask(self):
- raise nose.exc.SkipTest(
+ self.skipTest(
"Enabled emulation conflicts with enabled mask")
+
+
+class LdapIdentitySqlAssignment(sql.Base, test.TestCase, BaseLDAPIdentity):
+
+ def _set_config(self):
+ self.config([test.etcdir('keystone.conf.sample'),
+ test.testsdir('test_overrides.conf'),
+ test.testsdir('backend_ldap_sql.conf')])
+
+ def setUp(self):
+ self._set_config()
+ self.clear_database()
+ self.load_backends()
+ self.engine = self.get_engine()
+ sql.ModelBase.metadata.create_all(bind=self.engine)
+ self.load_fixtures(default_fixtures)
+ #defaulted by the data load
+ self.user_foo['enabled'] = True
+
+ def tearDown(self):
+ sql.ModelBase.metadata.drop_all(bind=self.engine)
+ self.engine.dispose()
+ sql.set_global_engine(None)
+
+ def test_domain_crud(self):
+ pass
+
+ def test_list_domains(self):
+ domains = self.identity_api.list_domains()
+ self.assertEquals(domains, [assignment.DEFAULT_DOMAIN])
+
+ def test_project_filter(self):
+ self.skipTest(
+ 'N/A: Not part of SQL backend')
+
+ def test_role_filter(self):
+ self.skipTest(
+ 'N/A: Not part of SQL backend')
diff --git a/tests/test_backend_memcache.py b/tests/test_backend_memcache.py
index 66401e09..7516e0dd 100644
--- a/tests/test_backend_memcache.py
+++ b/tests/test_backend_memcache.py
@@ -164,7 +164,7 @@ class MemcacheToken(test.TestCase, test_backend.TokenTests):
user_token_list = jsonutils.loads('[%s]' % user_record)
self.assertEquals(len(user_token_list), 2)
expired_token_ptk = self.token_api.driver._prefix_token_id(
- token.unique_id(expired_token_id))
+ expired_token_id)
expired_token = self.token_api.driver.client.get(expired_token_ptk)
expired_token['expires'] = (timeutils.utcnow() - expire_delta)
self.token_api.driver.client.set(expired_token_ptk, expired_token)
diff --git a/tests/test_backend_pam.py b/tests/test_backend_pam.py
index 3a66f014..b66faa9c 100644
--- a/tests/test_backend_pam.py
+++ b/tests/test_backend_pam.py
@@ -57,12 +57,12 @@ class PamIdentity(test.TestCase):
self.assertDictEqual(self.user_in, user_out)
def test_get_metadata_for_non_root(self):
- metadata_out = self.identity_api.get_metadata(self.user_in['id'],
- self.tenant_in['id'])
+ metadata_out = self.identity_api._get_metadata(self.user_in['id'],
+ self.tenant_in['id'])
self.assertDictEqual({}, metadata_out)
def test_get_metadata_for_root(self):
metadata = {'is_admin': True}
- metadata_out = self.identity_api.get_metadata('root',
- self.tenant_in['id'])
+ metadata_out = self.identity_api._get_metadata('root',
+ self.tenant_in['id'])
self.assertDictEqual(metadata, metadata_out)
diff --git a/tests/test_backend_sql.py b/tests/test_backend_sql.py
index 46d7c013..89276e86 100644
--- a/tests/test_backend_sql.py
+++ b/tests/test_backend_sql.py
@@ -16,6 +16,8 @@
import uuid
+import sqlalchemy
+
from keystone import test
from keystone.common import sql
@@ -57,6 +59,94 @@ class SqlTests(test.TestCase, sql.Base):
super(SqlTests, self).tearDown()
+class SqlModels(SqlTests):
+ def setUp(self):
+ super(SqlModels, self).setUp()
+
+ self.metadata = sql.ModelBase.metadata
+ self.metadata.bind = self.engine
+
+ def select_table(self, name):
+ table = sqlalchemy.Table(name,
+ self.metadata,
+ autoload=True)
+ s = sqlalchemy.select([table])
+ return s
+
+ def assertExpectedSchema(self, table, cols):
+ table = self.select_table(table)
+ for col, type_, length in cols:
+ self.assertIsInstance(table.c[col].type, type_)
+ if length:
+ self.assertEquals(table.c[col].type.length, length)
+
+ def test_user_model(self):
+ cols = (('id', sql.String, 64),
+ ('name', sql.String, 64),
+ ('password', sql.String, 128),
+ ('domain_id', sql.String, 64),
+ ('enabled', sql.Boolean, None),
+ ('extra', sql.JsonBlob, None))
+ self.assertExpectedSchema('user', cols)
+
+ def test_group_model(self):
+ cols = (('id', sql.String, 64),
+ ('name', sql.String, 64),
+ ('description', sql.Text, None),
+ ('domain_id', sql.String, 64),
+ ('extra', sql.JsonBlob, None))
+ self.assertExpectedSchema('group', cols)
+
+ def test_domain_model(self):
+ cols = (('id', sql.String, 64),
+ ('name', sql.String, 64),
+ ('enabled', sql.Boolean, None))
+ self.assertExpectedSchema('domain', cols)
+
+ def test_project_model(self):
+ cols = (('id', sql.String, 64),
+ ('name', sql.String, 64),
+ ('description', sql.Text, None),
+ ('domain_id', sql.String, 64),
+ ('enabled', sql.Boolean, None),
+ ('extra', sql.JsonBlob, None))
+ self.assertExpectedSchema('project', cols)
+
+ def test_role_model(self):
+ cols = (('id', sql.String, 64),
+ ('name', sql.String, 255))
+ self.assertExpectedSchema('role', cols)
+
+ def test_user_project_metadata_model(self):
+ cols = (('user_id', sql.String, 64),
+ ('project_id', sql.String, 64),
+ ('data', sql.JsonBlob, None))
+ self.assertExpectedSchema('user_project_metadata', cols)
+
+ def test_user_domain_metadata_model(self):
+ cols = (('user_id', sql.String, 64),
+ ('domain_id', sql.String, 64),
+ ('data', sql.JsonBlob, None))
+ self.assertExpectedSchema('user_domain_metadata', cols)
+
+ def test_group_project_metadata_model(self):
+ cols = (('group_id', sql.String, 64),
+ ('project_id', sql.String, 64),
+ ('data', sql.JsonBlob, None))
+ self.assertExpectedSchema('group_project_metadata', cols)
+
+ def test_group_domain_metadata_model(self):
+ cols = (('group_id', sql.String, 64),
+ ('domain_id', sql.String, 64),
+ ('data', sql.JsonBlob, None))
+ self.assertExpectedSchema('group_domain_metadata', cols)
+
+ def test_user_group_membership(self):
+ cols = (('group_id', sql.String, 64),
+ ('user_id', sql.String, 64))
+ self.assertExpectedSchema('user_group_membership', cols)
+
+
class SqlIdentity(SqlTests, test_backend.IdentityTests):
def test_password_hashed(self):
session = self.identity_api.get_session()
@@ -132,33 +222,51 @@ class SqlIdentity(SqlTests, test_backend.IdentityTests):
tenants = self.identity_api.get_projects_for_user(user['id'])
self.assertEquals(tenants, [])
- def test_delete_user_with_metadata(self):
- user = {'id': 'fake',
- 'name': 'fakeuser',
+ def test_metadata_removed_on_delete_user(self):
+ # A test to check that the internal representation
+ # or roles is correctly updated when a user is deleted
+ user = {'id': uuid.uuid4().hex,
+ 'name': uuid.uuid4().hex,
'domain_id': DEFAULT_DOMAIN_ID,
'password': 'passwd'}
- self.identity_api.create_user('fake', user)
- self.identity_api.create_metadata(user['id'],
- self.tenant_bar['id'],
- {'extra': 'extra'})
+ self.identity_api.create_user(user['id'], user)
+ role = {'id': uuid.uuid4().hex,
+ 'name': uuid.uuid4().hex}
+ self.identity_api.create_role(role['id'], role)
+ self.identity_api.add_role_to_user_and_project(
+ user['id'],
+ self.tenant_bar['id'],
+ role['id'])
self.identity_api.delete_user(user['id'])
+
+ # Now check whether the internal representation of roles
+ # has been deleted
self.assertRaises(exception.MetadataNotFound,
- self.identity_api.get_metadata,
+ self.assignment_api._get_metadata,
user['id'],
self.tenant_bar['id'])
- def test_delete_project_with_metadata(self):
- user = {'id': 'fake',
- 'name': 'fakeuser',
+ def test_metadata_removed_on_delete_project(self):
+ # A test to check that the internal representation
+ # or roles is correctly updated when a project is deleted
+ user = {'id': uuid.uuid4().hex,
+ 'name': uuid.uuid4().hex,
'domain_id': DEFAULT_DOMAIN_ID,
'password': 'passwd'}
- self.identity_api.create_user('fake', user)
- self.identity_api.create_metadata(user['id'],
- self.tenant_bar['id'],
- {'extra': 'extra'})
+ self.identity_api.create_user(user['id'], user)
+ role = {'id': uuid.uuid4().hex,
+ 'name': uuid.uuid4().hex}
+ self.identity_api.create_role(role['id'], role)
+ self.identity_api.add_role_to_user_and_project(
+ user['id'],
+ self.tenant_bar['id'],
+ role['id'])
self.identity_api.delete_project(self.tenant_bar['id'])
+
+ # Now check whether the internal representation of roles
+ # has been deleted
self.assertRaises(exception.MetadataNotFound,
- self.identity_api.get_metadata,
+ self.assignment_api._get_metadata,
user['id'],
self.tenant_bar['id'])
@@ -302,3 +410,7 @@ class SqlCatalog(SqlTests, test_backend.CatalogTests):
class SqlPolicy(SqlTests, test_backend.PolicyTests):
pass
+
+
+class SqlInheritance(SqlTests, test_backend.InheritanceTests):
+ pass
diff --git a/tests/test_cert_setup.py b/tests/test_cert_setup.py
index 74e5466a..e6c395e9 100644
--- a/tests/test_cert_setup.py
+++ b/tests/test_cert_setup.py
@@ -61,7 +61,6 @@ class CertSetupTestCase(test.TestCase):
self.controller = token.controllers.Auth()
def test_can_handle_missing_certs(self):
- self.opt_in_group('signing', token_format='PKI')
self.opt_in_group('signing', certfile='invalid')
user = {
'id': 'fake1',
diff --git a/tests/test_content_types.py b/tests/test_content_types.py
index 820dc0dd..ebb5dcef 100644
--- a/tests/test_content_types.py
+++ b/tests/test_content_types.py
@@ -18,11 +18,11 @@ import io
import uuid
from lxml import etree
-import nose.exc
import webtest
from keystone import test
+from keystone.common import extension
from keystone.common import serializer
from keystone.openstack.common import jsonutils
@@ -70,14 +70,12 @@ class RestfulTestCase(test.TestCase):
self.admin_app = webtest.TestApp(
self.loadapp('keystone', name='admin'))
- # TODO(termie): is_admin is being deprecated once the policy stuff
- # is all working
# TODO(termie): add an admin user to the fixtures and use that user
# override the fixtures, for now
- self.metadata_foobar = self.identity_api.update_metadata(
+ self.metadata_foobar = self.identity_api.add_role_to_user_and_project(
self.user_foo['id'],
self.tenant_bar['id'],
- dict(roles=[self.role_admin['id']], is_admin='1'))
+ self.role_admin['id'])
def tearDown(self):
"""Kill running servers and release references to avoid leaks."""
@@ -336,14 +334,14 @@ class CoreApiTests(object):
self.assertValidVersionResponse(r)
def test_public_extensions(self):
- self.public_request(path='/v2.0/extensions',)
-
- # TODO(dolph): can't test this without any public extensions defined
- # self.assertValidExtensionListResponse(r)
+ r = self.public_request(path='/v2.0/extensions')
+ self.assertValidExtensionListResponse(r,
+ extension.PUBLIC_EXTENSIONS)
def test_admin_extensions(self):
- r = self.admin_request(path='/v2.0/extensions',)
- self.assertValidExtensionListResponse(r)
+ r = self.admin_request(path='/v2.0/extensions')
+ self.assertValidExtensionListResponse(r,
+ extension.ADMIN_EXTENSIONS)
def test_admin_extensions_404(self):
self.admin_request(path='/v2.0/extensions/invalid-extension',
@@ -355,7 +353,8 @@ class CoreApiTests(object):
def test_admin_osksadm_extension(self):
r = self.admin_request(path='/v2.0/extensions/OS-KSADM')
- self.assertValidExtensionResponse(r)
+ self.assertValidExtensionResponse(r,
+ extension.ADMIN_EXTENSIONS)
def test_authenticate(self):
r = self.public_request(
@@ -403,10 +402,10 @@ class CoreApiTests(object):
self.assertValidAuthenticationResponse(r)
def test_validate_token_service_role(self):
- self.metadata_foobar = self.identity_api.update_metadata(
+ self.metadata_foobar = self.identity_api.add_role_to_user_and_project(
self.user_foo['id'],
self.tenant_service['id'],
- dict(roles=[self.role_service['id']]))
+ self.role_service['id'])
token = self.get_scoped_token(tenant_id='service')
r = self.admin_request(
@@ -471,7 +470,7 @@ class CoreApiTests(object):
self.assertValidTenantResponse(r)
def test_get_user_roles(self):
- raise nose.exc.SkipTest('Blocked by bug 933565')
+ self.skipTest('Blocked by bug 933565')
token = self.get_scoped_token()
r = self.admin_request(
@@ -613,24 +612,26 @@ class JsonTestCase(RestfulTestCase, CoreApiTests):
self.assertValidError(r.result['error'])
self.assertEqual(r.result['error']['code'], r.status_code)
- def assertValidExtension(self, extension):
+ def assertValidExtension(self, extension, expected):
super(JsonTestCase, self).assertValidExtension(extension)
-
- self.assertIsNotNone(extension.get('description'))
+ descriptions = [ext['description'] for ext in expected.itervalues()]
+ description = extension.get('description')
+ self.assertIsNotNone(description)
+ self.assertIn(description, descriptions)
self.assertIsNotNone(extension.get('links'))
self.assertNotEmpty(extension.get('links'))
for link in extension.get('links'):
self.assertValidExtensionLink(link)
- def assertValidExtensionListResponse(self, r):
+ def assertValidExtensionListResponse(self, r, expected):
self.assertIsNotNone(r.result.get('extensions'))
self.assertIsNotNone(r.result['extensions'].get('values'))
self.assertNotEmpty(r.result['extensions'].get('values'))
for extension in r.result['extensions']['values']:
- self.assertValidExtension(extension)
+ self.assertValidExtension(extension, expected)
- def assertValidExtensionResponse(self, r):
- self.assertValidExtension(r.result.get('extension'))
+ def assertValidExtensionResponse(self, r, expected):
+ self.assertValidExtension(r.result.get('extension'), expected)
def assertValidAuthenticationResponse(self, r,
require_service_catalog=False):
@@ -852,29 +853,31 @@ class XmlTestCase(RestfulTestCase, CoreApiTests):
self.assertValidError(xml)
self.assertEqual(xml.get('code'), str(r.status_code))
- def assertValidExtension(self, extension):
+ def assertValidExtension(self, extension, expected):
super(XmlTestCase, self).assertValidExtension(extension)
self.assertIsNotNone(extension.find(self._tag('description')))
self.assertTrue(extension.find(self._tag('description')).text)
links = extension.find(self._tag('links'))
self.assertNotEmpty(links.findall(self._tag('link')))
+ descriptions = [ext['description'] for ext in expected.itervalues()]
+ description = extension.find(self._tag('description')).text
+ self.assertIn(description, descriptions)
for link in links.findall(self._tag('link')):
self.assertValidExtensionLink(link)
- def assertValidExtensionListResponse(self, r):
+ def assertValidExtensionListResponse(self, r, expected):
xml = r.result
self.assertEqual(xml.tag, self._tag('extensions'))
-
self.assertNotEmpty(xml.findall(self._tag('extension')))
- for extension in xml.findall(self._tag('extension')):
- self.assertValidExtension(extension)
+ for ext in xml.findall(self._tag('extension')):
+ self.assertValidExtension(ext, expected)
- def assertValidExtensionResponse(self, r):
+ def assertValidExtensionResponse(self, r, expected):
xml = r.result
self.assertEqual(xml.tag, self._tag('extension'))
- self.assertValidExtension(xml)
+ self.assertValidExtension(xml, expected)
def assertValidVersion(self, version):
super(XmlTestCase, self).assertValidVersion(version)
diff --git a/tests/test_drivers.py b/tests/test_drivers.py
index 439b0d30..c83c1a89 100644
--- a/tests/test_drivers.py
+++ b/tests/test_drivers.py
@@ -1,6 +1,7 @@
import inspect
import unittest2 as unittest
+from keystone import assignment
from keystone import catalog
from keystone import exception
from keystone import identity
@@ -35,6 +36,10 @@ class TestDrivers(unittest.TestCase):
if name[0] != '_' and callable(method):
self.assertMethodNotImplemented(method)
+ def test_assignment_driver_unimplemented(self):
+ interface = assignment.Driver()
+ self.assertInterfaceNotImplemented(interface)
+
def test_catalog_driver_unimplemented(self):
interface = catalog.Driver()
self.assertInterfaceNotImplemented(interface)
diff --git a/tests/test_exception.py b/tests/test_exception.py
index ef06f633..d442d572 100644
--- a/tests/test_exception.py
+++ b/tests/test_exception.py
@@ -67,14 +67,14 @@ class ExceptionTestCase(test.TestCase):
attribute = uuid.uuid4().hex
e = exception.ValidationError(target=target, attribute=attribute)
self.assertValidJsonRendering(e)
- self.assertIn(target, str(e))
- self.assertIn(attribute, str(e))
+ self.assertIn(target, unicode(e))
+ self.assertIn(attribute, unicode(e))
def test_not_found(self):
target = uuid.uuid4().hex
e = exception.NotFound(target=target)
self.assertValidJsonRendering(e)
- self.assertIn(target, str(e))
+ self.assertIn(target, unicode(e))
def test_403_title(self):
e = exception.Forbidden()
@@ -83,6 +83,15 @@ class ExceptionTestCase(test.TestCase):
self.assertEqual('Forbidden', e.title)
self.assertEqual('Forbidden', j['error'].get('title'))
+ def test_unicode_message(self):
+ message = u'Comment \xe7a va'
+ e = exception.Error(message)
+
+ try:
+ self.assertEqual(unicode(e), message)
+ except UnicodeEncodeError:
+ self.fail("unicode error message not supported")
+
class SecurityErrorTestCase(ExceptionTestCase):
"""Tests whether security-related info is exposed to the API user."""
@@ -92,7 +101,7 @@ class SecurityErrorTestCase(ExceptionTestCase):
risky_info = uuid.uuid4().hex
e = exception.Unauthorized(message=risky_info)
self.assertValidJsonRendering(e)
- self.assertNotIn(risky_info, str(e))
+ self.assertNotIn(risky_info, unicode(e))
def test_unauthorized_exposure_in_debug(self):
self.opt(debug=True)
@@ -100,7 +109,7 @@ class SecurityErrorTestCase(ExceptionTestCase):
risky_info = uuid.uuid4().hex
e = exception.Unauthorized(message=risky_info)
self.assertValidJsonRendering(e)
- self.assertIn(risky_info, str(e))
+ self.assertIn(risky_info, unicode(e))
def test_forbidden_exposure(self):
self.opt(debug=False)
@@ -108,7 +117,7 @@ class SecurityErrorTestCase(ExceptionTestCase):
risky_info = uuid.uuid4().hex
e = exception.Forbidden(message=risky_info)
self.assertValidJsonRendering(e)
- self.assertNotIn(risky_info, str(e))
+ self.assertNotIn(risky_info, unicode(e))
def test_forbidden_exposure_in_debug(self):
self.opt(debug=True)
@@ -116,7 +125,7 @@ class SecurityErrorTestCase(ExceptionTestCase):
risky_info = uuid.uuid4().hex
e = exception.Forbidden(message=risky_info)
self.assertValidJsonRendering(e)
- self.assertIn(risky_info, str(e))
+ self.assertIn(risky_info, unicode(e))
def test_forbidden_action_exposure(self):
self.opt(debug=False)
@@ -125,12 +134,12 @@ class SecurityErrorTestCase(ExceptionTestCase):
action = uuid.uuid4().hex
e = exception.ForbiddenAction(message=risky_info, action=action)
self.assertValidJsonRendering(e)
- self.assertNotIn(risky_info, str(e))
- self.assertIn(action, str(e))
+ self.assertNotIn(risky_info, unicode(e))
+ self.assertIn(action, unicode(e))
e = exception.ForbiddenAction(action=risky_info)
self.assertValidJsonRendering(e)
- self.assertIn(risky_info, str(e))
+ self.assertIn(risky_info, unicode(e))
def test_forbidden_action_exposure_in_debug(self):
self.opt(debug=True)
@@ -139,17 +148,16 @@ class SecurityErrorTestCase(ExceptionTestCase):
e = exception.ForbiddenAction(message=risky_info)
self.assertValidJsonRendering(e)
- self.assertIn(risky_info, str(e))
+ self.assertIn(risky_info, unicode(e))
e = exception.ForbiddenAction(action=risky_info)
self.assertValidJsonRendering(e)
- self.assertIn(risky_info, str(e))
+ self.assertIn(risky_info, unicode(e))
- def test_unicode_message(self):
- message = u'Comment \xe7a va'
- e = exception.Error(message)
- self.assertEqual(e.message, message)
- try:
- unicode(e)
- except UnicodeEncodeError:
- self.fail("unicode error message not supported")
+ def test_unicode_argument_message(self):
+ self.opt(debug=False)
+
+ risky_info = u'\u7ee7\u7eed\u884c\u7f29\u8fdb\u6216'
+ e = exception.Forbidden(message=risky_info)
+ self.assertValidJsonRendering(e)
+ self.assertNotIn(risky_info, unicode(e))
diff --git a/tests/test_import_legacy.py b/tests/test_import_legacy.py
index bafc076a..9e164099 100644
--- a/tests/test_import_legacy.py
+++ b/tests/test_import_legacy.py
@@ -25,7 +25,6 @@ from keystone import test
from keystone.catalog.backends import templated as catalog_templated
from keystone.common.sql import legacy
-from keystone.common.sql import util as sql_util
from keystone import config
from keystone import identity
from keystone.identity.backends import sql as identity_sql
@@ -41,17 +40,17 @@ class ImportLegacy(test.TestCase):
test.testsdir('test_overrides.conf'),
test.testsdir('backend_sql.conf'),
test.testsdir('backend_sql_disk.conf')])
- sql_util.setup_test_database()
+ test.setup_test_database()
self.identity_man = identity.Manager()
self.identity_api = identity_sql.Identity()
def tearDown(self):
- sql_util.teardown_test_database()
+ test.teardown_test_database()
super(ImportLegacy, self).tearDown()
def setup_old_database(self, sql_dump):
sql_path = test.testsdir(sql_dump)
- db_path = test.testsdir('%s.db' % sql_dump)
+ db_path = test.tmpdir('%s.db' % sql_dump)
try:
os.unlink(db_path)
except OSError:
@@ -73,7 +72,7 @@ class ImportLegacy(test.TestCase):
self.assertEquals(user_ref['enabled'], True)
# check password hashing
- user_ref, tenant_ref, metadata_ref = self.identity_man.authenticate(
+ user_ref = self.identity_man.authenticate(
user_id=admin_id, password='secrete')
# check catalog
@@ -90,7 +89,7 @@ class ImportLegacy(test.TestCase):
self.assertEquals(user_ref['enabled'], True)
# check password hashing
- user_ref, tenant_ref, metadata_ref = self.identity_man.authenticate(
+ user_ref = self.identity_man.authenticate(
user_id=admin_id, password='secrete')
# check catalog
@@ -107,7 +106,7 @@ class ImportLegacy(test.TestCase):
self.assertEquals(user_ref['enabled'], True)
# check password hashing
- user_ref, tenant_ref, metadata_ref = self.identity_man.authenticate(
+ user_ref = self.identity_man.authenticate(
user_id=admin_id, password='secrete')
# check catalog
diff --git a/tests/test_injection.py b/tests/test_injection.py
index 4b6fc8ba..36cd0126 100644
--- a/tests/test_injection.py
+++ b/tests/test_injection.py
@@ -21,6 +21,10 @@ from keystone.common import dependency
class TestDependencyInjection(unittest.TestCase):
+ def tearDown(self):
+ dependency.reset()
+ super(TestDependencyInjection, self).tearDown()
+
def test_dependency_injection(self):
class Interface(object):
def do_work(self):
@@ -165,3 +169,43 @@ class TestDependencyInjection(unittest.TestCase):
with self.assertRaises(dependency.UnresolvableDependencyException):
Consumer()
+ dependency.resolve_future_dependencies()
+
+ def test_circular_dependency(self):
+ p1_name = uuid.uuid4().hex
+ p2_name = uuid.uuid4().hex
+
+ @dependency.provider(p1_name)
+ @dependency.requires(p2_name)
+ class P1(object):
+ pass
+
+ @dependency.provider(p2_name)
+ @dependency.requires(p1_name)
+ class P2(object):
+ pass
+
+ p1 = P1()
+ p2 = P2()
+
+ dependency.resolve_future_dependencies()
+
+ self.assertIs(getattr(p1, p2_name), p2)
+ self.assertIs(getattr(p2, p1_name), p1)
+
+ def test_reset(self):
+ # Can reset the registry of providers.
+
+ p_id = uuid.uuid4().hex
+
+ @dependency.provider(p_id)
+ class P(object):
+ pass
+
+ p_inst = P()
+
+ self.assertIs(dependency.REGISTRY[p_id], p_inst)
+
+ dependency.reset()
+
+ self.assertFalse(dependency.REGISTRY)
diff --git a/tests/test_keystoneclient.py b/tests/test_keystoneclient.py
index b9828559..38062d4b 100644
--- a/tests/test_keystoneclient.py
+++ b/tests/test_keystoneclient.py
@@ -17,8 +17,6 @@
import uuid
import webob
-import nose.exc
-
from keystone import test
from keystone import config
@@ -37,23 +35,25 @@ class CompatTestCase(test.TestCase):
def setUp(self):
super(CompatTestCase, self).setUp()
- revdir = test.checkout_vendor(*self.get_checkout())
- self.add_path(revdir)
- self.clear_module('keystoneclient')
+ # The backends should be loaded and initialized before the servers are
+ # started because the servers use the backends.
self.load_backends()
self.load_fixtures(default_fixtures)
+ # TODO(termie): add an admin user to the fixtures and use that user
+ # override the fixtures, for now
+ self.metadata_foobar = self.identity_api.add_role_to_user_and_project(
+ self.user_foo['id'],
+ self.tenant_bar['id'],
+ self.role_admin['id'])
+
self.public_server = self.serveapp('keystone', name='main')
self.admin_server = self.serveapp('keystone', name='admin')
- # TODO(termie): is_admin is being deprecated once the policy stuff
- # is all working
- # TODO(termie): add an admin user to the fixtures and use that user
- # override the fixtures, for now
- self.metadata_foobar = self.identity_api.update_metadata(
- self.user_foo['id'], self.tenant_bar['id'],
- dict(roles=[self.role_admin['id']], is_admin='1'))
+ revdir = test.checkout_vendor(*self.get_checkout())
+ self.add_path(revdir)
+ self.clear_module('keystoneclient')
def tearDown(self):
self.public_server.kill()
@@ -537,7 +537,7 @@ class KeystoneClientTests(object):
user=uuid.uuid4().hex)
def test_user_update_tenant_404(self):
- raise nose.exc.SkipTest('N/A')
+ self.skipTest('N/A')
from keystoneclient import exceptions as client_exceptions
client = self.get_client(admin=True)
self.assertRaises(client_exceptions.NotFound,
@@ -840,6 +840,28 @@ class KcMasterTestCase(CompatTestCase, KeystoneClientTests):
def get_checkout(self):
return KEYSTONECLIENT_REPO, 'master'
+ def test_ec2_auth(self):
+ client = self.get_client()
+ cred = client.ec2.create(user_id=self.user_foo['id'],
+ tenant_id=self.tenant_bar['id'])
+
+ from keystoneclient.contrib.ec2 import utils as ec2_utils
+ signer = ec2_utils.Ec2Signer(cred.secret)
+ credentials = {'params': {'SignatureVersion': '2'},
+ 'access': cred.access,
+ 'verb': 'GET',
+ 'host': 'localhost',
+ 'path': '/thisisgoingtowork'}
+ signature = signer.generate(credentials)
+ credentials['signature'] = signature
+ url = '%s/ec2tokens' % (client.auth_url)
+ (resp, token) = client.request(url=url,
+ method='POST',
+ body={'credentials': credentials})
+ # make sure we have a v2 token
+ self.assertEqual(resp.status_code, 200)
+ self.assertIn('access', token)
+
def test_tenant_add_and_remove_user(self):
client = self.get_client(admin=True)
client.roles.add_user_role(tenant=self.tenant_bar['id'],
@@ -1086,10 +1108,10 @@ class KcEssex3TestCase(CompatTestCase, KeystoneClientTests):
self.assertTrue(len(roles) > 0)
def test_role_list_404(self):
- raise nose.exc.SkipTest('N/A')
+ self.skipTest('N/A')
def test_authenticate_and_delete_token(self):
- raise nose.exc.SkipTest('N/A')
+ self.skipTest('N/A')
def test_user_create_update_delete(self):
from keystoneclient import exceptions as client_exceptions
@@ -1133,16 +1155,16 @@ class KcEssex3TestCase(CompatTestCase, KeystoneClientTests):
user.id)
def test_user_update_404(self):
- raise nose.exc.SkipTest('N/A')
+ self.skipTest('N/A')
def test_endpoint_create_404(self):
- raise nose.exc.SkipTest('N/A')
+ self.skipTest('N/A')
def test_endpoint_delete_404(self):
- raise nose.exc.SkipTest('N/A')
+ self.skipTest('N/A')
def test_policy_crud(self):
- raise nose.exc.SkipTest('N/A due to lack of endpoint CRUD')
+ self.skipTest('N/A due to lack of endpoint CRUD')
class Kc11TestCase(CompatTestCase, KeystoneClientTests):
@@ -1150,4 +1172,4 @@ class Kc11TestCase(CompatTestCase, KeystoneClientTests):
return KEYSTONECLIENT_REPO, '0.1.1'
def test_policy_crud(self):
- raise nose.exc.SkipTest('N/A')
+ self.skipTest('N/A')
diff --git a/tests/test_keystoneclient_sql.py b/tests/test_keystoneclient_sql.py
index 5706bef5..166d808c 100644
--- a/tests/test_keystoneclient_sql.py
+++ b/tests/test_keystoneclient_sql.py
@@ -16,8 +16,6 @@
import uuid
-import nose.exc
-
from keystone import test
from keystone.common import sql
@@ -109,7 +107,7 @@ class KcMasterSqlTestCase(test_keystoneclient.KcMasterTestCase, sql.Base):
# the client and essentially refers to a non-existent
# policy manager in the v2 client. this test needs to be
# moved to a test suite running against the v3 api
- raise nose.exc.SkipTest('Written prior to v3 client; needs refactor')
+ self.skipTest('Written prior to v3 client; needs refactor')
from keystoneclient import exceptions as client_exceptions
client = self.get_client(admin=True)
diff --git a/tests/test_middleware.py b/tests/test_middleware.py
index 38ba09e9..9f9d3fd2 100644
--- a/tests/test_middleware.py
+++ b/tests/test_middleware.py
@@ -154,7 +154,7 @@ class XmlBodyMiddlewareTest(test.TestCase):
self.assertTrue(jsonutils.loads(req.body))
def test_json_unnaffected(self):
- """JSON-only requests should be unnaffected by the XML middleware."""
+ """JSON-only requests should be unaffected by the XML middleware."""
content_type = 'application/json'
body = '{"container": {"attribute": "value"}}'
req = make_request(body=body, content_type=content_type, method='POST')
diff --git a/tests/test_migrate_nova_auth.py b/tests/test_migrate_nova_auth.py
deleted file mode 100644
index 3a122940..00000000
--- a/tests/test_migrate_nova_auth.py
+++ /dev/null
@@ -1,157 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2012 OpenStack LLC
-#
-# Licensed under the Apache License, Version 2.0 (the 'License'); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an 'AS IS' BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import uuid
-
-from keystone import test
-
-from keystone.common.sql import nova
-from keystone.common.sql import util as sql_util
-from keystone import config
-from keystone.contrib.ec2.backends import sql as ec2_sql
-from keystone import identity
-
-
-CONF = config.CONF
-DEFAULT_DOMAIN_ID = CONF.identity.default_domain_id
-
-
-FIXTURE = {
- 'users': [
- {'id': 'user1', 'name': 'uname1', 'password': 'acc1'},
- {'id': 'user4', 'name': 'uname4', 'password': 'acc1'},
- {'id': 'user2', 'name': 'uname2', 'password': 'acc2'},
- {'id': 'user3', 'name': 'uname3', 'password': 'acc3'},
- ],
- 'roles': ['role1', 'role2', 'role3'],
- 'role_user_tenant_list': [
- {'user_id': 'user1', 'role': 'role1', 'tenant_id': 'proj1'},
- {'user_id': 'user1', 'role': 'role2', 'tenant_id': 'proj1'},
- {'user_id': 'user4', 'role': 'role1', 'tenant_id': 'proj4'},
- {'user_id': 'user2', 'role': 'role1', 'tenant_id': 'proj1'},
- {'user_id': 'user2', 'role': 'role1', 'tenant_id': 'proj2'},
- {'user_id': 'user2', 'role': 'role2', 'tenant_id': 'proj2'},
- {'user_id': 'user3', 'role': 'role3', 'tenant_id': 'proj1'},
- ],
- 'user_tenant_list': [
- {'tenant_id': 'proj1', 'user_id': 'user1'},
- {'tenant_id': 'proj4', 'user_id': 'user4'},
- {'tenant_id': 'proj1', 'user_id': 'user2'},
- {'tenant_id': 'proj2', 'user_id': 'user2'},
- {'tenant_id': 'proj1', 'user_id': 'user3'},
- ],
- 'ec2_credentials': [
- {'access_key': 'acc1', 'secret_key': 'sec1', 'user_id': 'user1'},
- {'access_key': 'acc4', 'secret_key': 'sec4', 'user_id': 'user4'},
- {'access_key': 'acc2', 'secret_key': 'sec2', 'user_id': 'user2'},
- {'access_key': 'acc3', 'secret_key': 'sec3', 'user_id': 'user3'},
- ],
- 'tenants': [
- {'description': 'desc1', 'id': 'proj1', 'name': 'pname1'},
- {'description': 'desc4', 'id': 'proj4', 'name': 'pname4'},
- {'description': 'desc2', 'id': 'proj2', 'name': 'pname2'},
- ],
-}
-
-
-class MigrateNovaAuth(test.TestCase):
- def setUp(self):
- super(MigrateNovaAuth, self).setUp()
- self.config([test.etcdir('keystone.conf.sample'),
- test.testsdir('test_overrides.conf'),
- test.testsdir('backend_sql.conf'),
- test.testsdir('backend_sql_disk.conf')])
- sql_util.setup_test_database()
- self.identity_api = identity.Manager()
- self.ec2_api = ec2_sql.Ec2()
-
- def tearDown(self):
- sql_util.teardown_test_database()
- super(MigrateNovaAuth, self).tearDown()
-
- def _create_role(self, role_name):
- role_id = uuid.uuid4().hex
- role_dict = {'id': role_id, 'name': role_name}
- self.identity_api.create_role(role_id, role_dict)
-
- def test_import(self):
- self._create_role('role1')
-
- nova.import_auth(FIXTURE)
-
- users = {}
- for user in ['user1', 'user2', 'user3', 'user4']:
- users[user] = self.identity_api.get_user_by_name(
- user, DEFAULT_DOMAIN_ID)
-
- tenants = {}
- for tenant in ['proj1', 'proj2', 'proj4']:
- tenants[tenant] = self.identity_api.get_project_by_name(
- tenant, DEFAULT_DOMAIN_ID)
-
- membership_map = {
- 'user1': ['proj1'],
- 'user2': ['proj1', 'proj2'],
- 'user3': ['proj1'],
- 'user4': ['proj4'],
- }
-
- for (old_user, old_projects) in membership_map.iteritems():
- user = users[old_user]
- membership = self.identity_api.get_projects_for_user(user['id'])
- expected = [tenants[t]['id'] for t in old_projects]
- self.assertEqual(set(expected), set(membership))
- for tenant_id in membership:
- password = None
- for _user in FIXTURE['users']:
- if _user['id'] == old_user:
- password = _user['password']
- self.identity_api.authenticate(user['id'], tenant_id, password)
-
- for ec2_cred in FIXTURE['ec2_credentials']:
- user_id = users[ec2_cred['user_id']]['id']
- for tenant_id in self.identity_api.get_projects_for_user(user_id):
- access = '%s:%s' % (tenant_id, ec2_cred['access_key'])
- cred = self.ec2_api.get_credential(access)
- actual = cred['secret']
- expected = ec2_cred['secret_key']
- self.assertEqual(expected, actual)
-
- roles = self.identity_api.list_roles()
- role_names = set([role['name'] for role in roles])
- self.assertEqual(role_names, set(['role2', 'role1', 'role3',
- CONF.member_role_name]))
-
- assignment_map = {
- 'user1': {'proj1': ['role1', 'role2']},
- 'user2': {'proj1': ['role1'], 'proj2': ['role1', 'role2']},
- 'user3': {'proj1': ['role3']},
- 'user4': {'proj4': ['role1']},
- }
-
- for (old_user, old_project_map) in assignment_map.iteritems():
- tenant_names = ['proj1', 'proj2', 'proj4']
- for tenant_name in tenant_names:
- user = users[old_user]
- tenant = tenants[tenant_name]
- roles = self.identity_api.get_roles_for_user_and_project(
- user['id'], tenant['id'])
- actual = [self.identity_api.get_role(role_id)['name']
- for role_id in roles]
- if CONF.member_role_name in actual:
- actual.remove(CONF.member_role_name)
- expected = old_project_map.get(tenant_name, [])
- self.assertEqual(set(actual), set(expected))
diff --git a/tests/test_no_admin_token_auth.py b/tests/test_no_admin_token_auth.py
new file mode 100644
index 00000000..ffdaa7a8
--- /dev/null
+++ b/tests/test_no_admin_token_auth.py
@@ -0,0 +1,47 @@
+
+import os
+import webtest
+
+from keystone import test
+
+
+def _generate_paste_config():
+ # Generate a file, based on keystone-paste.ini, that doesn't include
+ # admin_token_auth in the pipeline
+
+ with open(test.etcdir('keystone-paste.ini'), 'r') as f:
+ contents = f.read()
+
+ new_contents = contents.replace(' admin_token_auth ', ' ')
+
+ with open(test.tmpdir('no_admin_token_auth-paste.ini'), 'w') as f:
+ f.write(new_contents)
+
+
+class TestNoAdminTokenAuth(test.TestCase):
+ def setUp(self):
+ super(TestNoAdminTokenAuth, self).setUp()
+ self.load_backends()
+
+ _generate_paste_config()
+
+ self.admin_app = webtest.TestApp(
+ self.loadapp(test.tmpdir('no_admin_token_auth'), name='admin'),
+ extra_environ=dict(REMOTE_ADDR='127.0.0.1'))
+
+ def tearDown(self):
+ self.admin_app = None
+ os.remove(test.tmpdir('no_admin_token_auth-paste.ini'))
+
+ def test_request_no_admin_token_auth(self):
+ # This test verifies that if the admin_token_auth middleware isn't
+ # in the paste pipeline that users can still make requests.
+
+ # Note(blk-u): Picked /v2.0/tenants because it's an operation that
+ # requires is_admin in the context, any operation that requires
+ # is_admin would work for this test.
+ REQ_PATH = '/v2.0/tenants'
+
+ # If the following does not raise, then the test is successful.
+ self.admin_app.get(REQ_PATH, headers={'X-Auth-Token': 'NotAdminToken'},
+ status=401)
diff --git a/tests/test_pki_token_provider.conf b/tests/test_pki_token_provider.conf
new file mode 100644
index 00000000..255972c3
--- /dev/null
+++ b/tests/test_pki_token_provider.conf
@@ -0,0 +1,2 @@
+[token]
+provider = keystone.token.providers.pki.Provider
diff --git a/tests/test_sql_core.py b/tests/test_sql_core.py
index d8f2a4f7..e60005f5 100644
--- a/tests/test_sql_core.py
+++ b/tests/test_sql_core.py
@@ -17,6 +17,130 @@ from keystone.common import sql
from keystone import test
+class CallbackMonitor:
+ def __init__(self, expect_called=True, raise_=False):
+ self.expect_called = expect_called
+ self.called = False
+ self._complete = False
+ self._raise = raise_
+
+ def call_this(self):
+ if self._complete:
+ return
+
+ if not self.expect_called:
+ raise Exception("Did not expect callback.")
+
+ if self.called:
+ raise Exception("Callback already called.")
+
+ self.called = True
+
+ if self._raise:
+ raise Exception("When called, raises.")
+
+ def check(self):
+ if self.expect_called:
+ if not self.called:
+ raise Exception("Expected function to be called.")
+ self._complete = True
+
+
+class TestGlobalEngine(test.TestCase):
+
+ def tearDown(self):
+ sql.set_global_engine(None)
+ super(TestGlobalEngine, self).tearDown()
+
+ def test_notify_on_set(self):
+ # If call sql.set_global_engine(), notify callbacks get called.
+
+ cb_mon = CallbackMonitor()
+
+ sql.register_global_engine_callback(cb_mon.call_this)
+ fake_engine = object()
+ sql.set_global_engine(fake_engine)
+
+ cb_mon.check()
+
+ def test_multi_notify(self):
+ # You can also set multiple notify callbacks and they each get called.
+
+ cb_mon1 = CallbackMonitor()
+ cb_mon2 = CallbackMonitor()
+
+ sql.register_global_engine_callback(cb_mon1.call_this)
+ sql.register_global_engine_callback(cb_mon2.call_this)
+
+ fake_engine = object()
+ sql.set_global_engine(fake_engine)
+
+ cb_mon1.check()
+ cb_mon2.check()
+
+ def test_notify_once(self):
+ # After a callback is called, it's not called again if set global
+ # engine again.
+
+ cb_mon = CallbackMonitor()
+
+ sql.register_global_engine_callback(cb_mon.call_this)
+ fake_engine = object()
+ sql.set_global_engine(fake_engine)
+
+ fake_engine = object()
+ # Note that cb_mon.call_this would raise if it's called again.
+ sql.set_global_engine(fake_engine)
+
+ cb_mon.check()
+
+ def test_set_same_engine(self):
+ # If you set the global engine to the same engine, callbacks don't get
+ # called.
+
+ fake_engine = object()
+
+ sql.set_global_engine(fake_engine)
+
+ cb_mon = CallbackMonitor(expect_called=False)
+ sql.register_global_engine_callback(cb_mon.call_this)
+
+ # Note that cb_mon.call_this would raise if it's called.
+ sql.set_global_engine(fake_engine)
+
+ cb_mon.check()
+
+ def test_notify_register_same(self):
+ # If you register the same callback twice, only gets called once.
+ cb_mon = CallbackMonitor()
+
+ sql.register_global_engine_callback(cb_mon.call_this)
+ sql.register_global_engine_callback(cb_mon.call_this)
+
+ fake_engine = object()
+ # Note that cb_mon.call_this would raise if it's called twice.
+ sql.set_global_engine(fake_engine)
+
+ cb_mon.check()
+
+ def test_callback_throws(self):
+ # If a callback function raises,
+ # a) the caller doesn't know about it,
+ # b) other callbacks are still called
+
+ cb_mon1 = CallbackMonitor(raise_=True)
+ cb_mon2 = CallbackMonitor()
+
+ sql.register_global_engine_callback(cb_mon1.call_this)
+ sql.register_global_engine_callback(cb_mon2.call_this)
+
+ fake_engine = object()
+ sql.set_global_engine(fake_engine)
+
+ cb_mon1.check()
+ cb_mon2.check()
+
+
class TestBase(test.TestCase):
def tearDown(self):
@@ -38,3 +162,21 @@ class TestBase(test.TestCase):
engine1 = base.get_engine()
engine2 = base.get_engine(allow_global_engine=False)
self.assertIsNot(engine1, engine2)
+
+ def test_get_session(self):
+ # autocommit and expire_on_commit flags to get_session() are passed on
+ # to the session created.
+
+ base = sql.Base()
+ session = base.get_session(autocommit=False, expire_on_commit=True)
+
+ self.assertFalse(session.autocommit)
+ self.assertTrue(session.expire_on_commit)
+
+ def test_get_session_invalidated(self):
+ # If clear the global engine, a new engine is used for get_session().
+ base = sql.Base()
+ session1 = base.get_session()
+ sql.set_global_engine(None)
+ session2 = base.get_session()
+ self.assertIsNot(session1.bind, session2.bind)
diff --git a/tests/test_sql_upgrade.py b/tests/test_sql_upgrade.py
index ac4e5637..cf82b814 100644
--- a/tests/test_sql_upgrade.py
+++ b/tests/test_sql_upgrade.py
@@ -506,6 +506,10 @@ class SqlUpgradeTests(test.TestCase):
def test_downgrade_to_0(self):
self.upgrade(self.max_version)
+
+ if self.engine.name == 'mysql':
+ self._mysql_check_all_tables_innodb()
+
self.downgrade(0)
for table_name in ["user", "token", "role", "user_tenant_membership",
"metadata"]:
@@ -590,6 +594,22 @@ class SqlUpgradeTests(test.TestCase):
'data': json.dumps({"roles": [role2['id']]})}
session.execute(metadata_table.insert().values(role_grant))
+ # Create another user to test the case where member_role_id is already
+ # assigned.
+ user2 = {'id': uuid.uuid4().hex,
+ 'name': uuid.uuid4().hex,
+ 'domain_id': domain['id'],
+ 'password': uuid.uuid4().hex,
+ 'enabled': True,
+ 'extra': json.dumps({})}
+ session.execute(user_table.insert().values(user2))
+
+ # Grant CONF.member_role_id to User2
+ role_grant = {'user_id': user2['id'],
+ 'tenant_id': project['id'],
+ 'data': json.dumps({"roles": [CONF.member_role_id]})}
+ session.execute(metadata_table.insert().values(role_grant))
+
session.commit()
self.upgrade(17)
@@ -597,17 +617,19 @@ class SqlUpgradeTests(test.TestCase):
user_project_metadata_table = sqlalchemy.Table(
'user_project_metadata', self.metadata, autoload=True)
- r = session.execute('select data from metadata where '
- 'user_id=:user and tenant_id=:tenant',
- {'user': user['id'], 'tenant': project['id']})
+ s = sqlalchemy.select([metadata_table.c.data]).where(
+ (metadata_table.c.user_id == user['id']) &
+ (metadata_table.c.tenant_id == project['id']))
+ r = session.execute(s)
test_project1 = json.loads(r.fetchone()['data'])
self.assertEqual(len(test_project1['roles']), 1)
self.assertIn(role['id'], test_project1['roles'])
# Test user in project2 has role2
- r = session.execute('select data from metadata where '
- 'user_id=:user and tenant_id=:tenant',
- {'user': user['id'], 'tenant': project2['id']})
+ s = sqlalchemy.select([metadata_table.c.data]).where(
+ (metadata_table.c.user_id == user['id']) &
+ (metadata_table.c.tenant_id == project2['id']))
+ r = session.execute(s)
test_project2 = json.loads(r.fetchone()['data'])
self.assertEqual(len(test_project2['roles']), 1)
self.assertIn(role2['id'], test_project2['roles'])
@@ -615,9 +637,10 @@ class SqlUpgradeTests(test.TestCase):
# Test for user in project has role in user_project_metadata
# Migration 17 does not properly migrate this data, so this should
# be None.
- r = session.execute('select data from user_project_metadata where '
- 'user_id=:user and project_id=:project',
- {'user': user['id'], 'project': project['id']})
+ s = sqlalchemy.select([user_project_metadata_table.c.data]).where(
+ (user_project_metadata_table.c.user_id == user['id']) &
+ (user_project_metadata_table.c.project_id == project['id']))
+ r = session.execute(s)
self.assertIsNone(r.fetchone())
# Create a conflicting user-project in user_project_metadata with
@@ -628,6 +651,14 @@ class SqlUpgradeTests(test.TestCase):
'data': data}
cmd = user_project_metadata_table.insert().values(role_grant)
self.engine.execute(cmd)
+
+ # Create another conflicting user-project for User2
+ data = json.dumps({"roles": [role2['id']]})
+ role_grant = {'user_id': user2['id'],
+ 'project_id': project['id'],
+ 'data': data}
+ cmd = user_project_metadata_table.insert().values(role_grant)
+ self.engine.execute(cmd)
# End Scaffolding
session.commit()
@@ -638,9 +669,10 @@ class SqlUpgradeTests(test.TestCase):
# The user-project pairs should have all roles from the previous
# metadata table in addition to any roles currently in
# user_project_metadata
- r = session.execute('select data from user_project_metadata where '
- 'user_id=:user and project_id=:project',
- {'user': user['id'], 'project': project['id']})
+ s = sqlalchemy.select([user_project_metadata_table.c.data]).where(
+ (user_project_metadata_table.c.user_id == user['id']) &
+ (user_project_metadata_table.c.project_id == project['id']))
+ r = session.execute(s)
role_ids = json.loads(r.fetchone()['data'])['roles']
self.assertEqual(len(role_ids), 3)
self.assertIn(CONF.member_role_id, role_ids)
@@ -649,9 +681,10 @@ class SqlUpgradeTests(test.TestCase):
# pairs that only existed in old metadata table should be in
# user_project_metadata
- r = session.execute('select data from user_project_metadata where '
- 'user_id=:user and project_id=:project',
- {'user': user['id'], 'project': project2['id']})
+ s = sqlalchemy.select([user_project_metadata_table.c.data]).where(
+ (user_project_metadata_table.c.user_id == user['id']) &
+ (user_project_metadata_table.c.project_id == project2['id']))
+ r = session.execute(s)
role_ids = json.loads(r.fetchone()['data'])['roles']
self.assertEqual(len(role_ids), 2)
self.assertIn(CONF.member_role_id, role_ids)
@@ -815,6 +848,344 @@ class SqlUpgradeTests(test.TestCase):
self.assertEqual(ref.legacy_endpoint_id, legacy_endpoint_id)
self.assertEqual(ref.extra, '{}')
+ def test_group_project_FK_fixup(self):
+ # To create test data we must start before we broke in the
+ # group_project_metadata table in 015.
+ self.upgrade(14)
+ session = self.Session()
+
+ domain_table = sqlalchemy.Table('domain', self.metadata, autoload=True)
+ group_table = sqlalchemy.Table('group', self.metadata, autoload=True)
+ tenant_table = sqlalchemy.Table('tenant', self.metadata, autoload=True)
+ role_table = sqlalchemy.Table('role', self.metadata, autoload=True)
+ group_project_metadata_table = sqlalchemy.Table(
+ 'group_project_metadata', self.metadata, autoload=True)
+
+ # Create a Domain
+ domain = {'id': uuid.uuid4().hex,
+ 'name': uuid.uuid4().hex,
+ 'enabled': True}
+ session.execute(domain_table.insert().values(domain))
+
+ # Create two Tenants
+ tenant = {'id': uuid.uuid4().hex,
+ 'name': uuid.uuid4().hex,
+ 'extra': "{}"}
+ session.execute(tenant_table.insert().values(tenant))
+
+ tenant1 = {'id': uuid.uuid4().hex,
+ 'name': uuid.uuid4().hex,
+ 'extra': "{}"}
+ session.execute(tenant_table.insert().values(tenant1))
+
+ # Create a Group
+ group = {'id': uuid.uuid4().hex,
+ 'name': uuid.uuid4().hex,
+ 'domain_id': domain['id'],
+ 'extra': json.dumps({})}
+ session.execute(group_table.insert().values(group))
+
+ # Create roles
+ role_list = []
+ for _ in range(2):
+ role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex}
+ session.execute(role_table.insert().values(role))
+ role_list.append(role)
+
+ # Grant Role to User on Project
+ role_grant = {'group_id': group['id'],
+ 'project_id': tenant['id'],
+ 'data': json.dumps({'roles': [role_list[0]['id']]})}
+ session.execute(
+ group_project_metadata_table.insert().values(role_grant))
+
+ role_grant = {'group_id': group['id'],
+ 'project_id': tenant1['id'],
+ 'data': json.dumps({'roles': [role_list[1]['id']]})}
+ session.execute(
+ group_project_metadata_table.insert().values(role_grant))
+
+ session.commit()
+
+ # Now upgrade and fix up the FKs
+ self.upgrade(28)
+ self.assertTableExists('group_project_metadata')
+ self.assertTableExists('project')
+ self.assertTableDoesNotExist('tenant')
+
+ s = sqlalchemy.select([group_project_metadata_table.c.data]).where(
+ (group_project_metadata_table.c.group_id == group['id']) &
+ (group_project_metadata_table.c.project_id == tenant['id']))
+ r = session.execute(s)
+ data = json.loads(r.fetchone()['data'])
+ self.assertEqual(len(data['roles']), 1)
+ self.assertIn(role_list[0]['id'], data['roles'])
+
+ s = sqlalchemy.select([group_project_metadata_table.c.data]).where(
+ (group_project_metadata_table.c.group_id == group['id']) &
+ (group_project_metadata_table.c.project_id == tenant1['id']))
+ r = session.execute(s)
+ data = json.loads(r.fetchone()['data'])
+ self.assertEqual(len(data['roles']), 1)
+ self.assertIn(role_list[1]['id'], data['roles'])
+
+ self.downgrade(27)
+ self.assertTableExists('group_project_metadata')
+ self.assertTableExists('project')
+ self.assertTableDoesNotExist('tenant')
+
+ def test_assignment_metadata_migration(self):
+ self.upgrade(28)
+ # Scaffolding
+ session = self.Session()
+
+ domain_table = sqlalchemy.Table('domain', self.metadata, autoload=True)
+ user_table = sqlalchemy.Table('user', self.metadata, autoload=True)
+ group_table = sqlalchemy.Table('group', self.metadata, autoload=True)
+ role_table = sqlalchemy.Table('role', self.metadata, autoload=True)
+ project_table = sqlalchemy.Table(
+ 'project', self.metadata, autoload=True)
+ user_project_metadata_table = sqlalchemy.Table(
+ 'user_project_metadata', self.metadata, autoload=True)
+ user_domain_metadata_table = sqlalchemy.Table(
+ 'user_domain_metadata', self.metadata, autoload=True)
+ group_project_metadata_table = sqlalchemy.Table(
+ 'group_project_metadata', self.metadata, autoload=True)
+ group_domain_metadata_table = sqlalchemy.Table(
+ 'group_domain_metadata', self.metadata, autoload=True)
+
+ # Create a Domain
+ domain = {'id': uuid.uuid4().hex,
+ 'name': uuid.uuid4().hex,
+ 'enabled': True}
+ session.execute(domain_table.insert().values(domain))
+
+ # Create anther Domain
+ domain2 = {'id': uuid.uuid4().hex,
+ 'name': uuid.uuid4().hex,
+ 'enabled': True}
+ session.execute(domain_table.insert().values(domain2))
+
+ # Create a Project
+ project = {'id': uuid.uuid4().hex,
+ 'name': uuid.uuid4().hex,
+ 'domain_id': domain['id'],
+ 'extra': "{}"}
+ session.execute(project_table.insert().values(project))
+
+ # Create another Project
+ project2 = {'id': uuid.uuid4().hex,
+ 'name': uuid.uuid4().hex,
+ 'domain_id': domain['id'],
+ 'extra': "{}"}
+ session.execute(project_table.insert().values(project2))
+
+ # Create a User
+ user = {'id': uuid.uuid4().hex,
+ 'name': uuid.uuid4().hex,
+ 'domain_id': domain['id'],
+ 'password': uuid.uuid4().hex,
+ 'enabled': True,
+ 'extra': json.dumps({})}
+ session.execute(user_table.insert().values(user))
+
+ # Create a Group
+ group = {'id': uuid.uuid4().hex,
+ 'name': uuid.uuid4().hex,
+ 'domain_id': domain['id'],
+ 'extra': json.dumps({})}
+ session.execute(group_table.insert().values(group))
+
+ # Create roles
+ role_list = []
+ for _ in range(7):
+ role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex}
+ session.execute(role_table.insert().values(role))
+ role_list.append(role)
+
+ # Grant Role to User on Project
+ role_grant = {'user_id': user['id'],
+ 'project_id': project['id'],
+ 'data': json.dumps({'roles': [role_list[0]['id']]})}
+ session.execute(
+ user_project_metadata_table.insert().values(role_grant))
+
+ role_grant = {'user_id': user['id'],
+ 'project_id': project2['id'],
+ 'data': json.dumps({'roles': [role_list[1]['id']]})}
+ session.execute(
+ user_project_metadata_table.insert().values(role_grant))
+
+ # Grant Role to Group on different Project
+ role_grant = {'group_id': group['id'],
+ 'project_id': project2['id'],
+ 'data': json.dumps({'roles': [role_list[2]['id']]})}
+ session.execute(
+ group_project_metadata_table.insert().values(role_grant))
+
+ # Grant Role to User on Domain
+ role_grant = {'user_id': user['id'],
+ 'domain_id': domain['id'],
+ 'data': json.dumps({'roles': [role_list[3]['id']]})}
+ session.execute(user_domain_metadata_table.insert().values(role_grant))
+
+ # Grant Role to Group on Domain
+ role_grant = {'group_id': group['id'],
+ 'domain_id': domain['id'],
+ 'data': json.dumps(
+ {'roles': [role_list[4]['id']],
+ 'other': 'somedata'})}
+ session.execute(
+ group_domain_metadata_table.insert().values(role_grant))
+
+ session.commit()
+
+ self.upgrade(29)
+ s = sqlalchemy.select([user_project_metadata_table.c.data]).where(
+ (user_project_metadata_table.c.user_id == user['id']) &
+ (user_project_metadata_table.c.project_id == project['id']))
+ r = session.execute(s)
+ data = json.loads(r.fetchone()['data'])
+ self.assertEqual(len(data['roles']), 1)
+ self.assertIn({'id': role_list[0]['id']}, data['roles'])
+
+ s = sqlalchemy.select([user_project_metadata_table.c.data]).where(
+ (user_project_metadata_table.c.user_id == user['id']) &
+ (user_project_metadata_table.c.project_id == project2['id']))
+ r = session.execute(s)
+ data = json.loads(r.fetchone()['data'])
+ self.assertEqual(len(data['roles']), 1)
+ self.assertIn({'id': role_list[1]['id']}, data['roles'])
+
+ s = sqlalchemy.select([group_project_metadata_table.c.data]).where(
+ (group_project_metadata_table.c.group_id == group['id']) &
+ (group_project_metadata_table.c.project_id == project2['id']))
+ r = session.execute(s)
+ data = json.loads(r.fetchone()['data'])
+ self.assertEqual(len(data['roles']), 1)
+ self.assertIn({'id': role_list[2]['id']}, data['roles'])
+
+ s = sqlalchemy.select([user_domain_metadata_table.c.data]).where(
+ (user_domain_metadata_table.c.user_id == user['id']) &
+ (user_domain_metadata_table.c.domain_id == domain['id']))
+ r = session.execute(s)
+ data = json.loads(r.fetchone()['data'])
+ self.assertEqual(len(data['roles']), 1)
+ self.assertIn({'id': role_list[3]['id']}, data['roles'])
+
+ s = sqlalchemy.select([group_domain_metadata_table.c.data]).where(
+ (group_domain_metadata_table.c.group_id == group['id']) &
+ (group_domain_metadata_table.c.domain_id == domain['id']))
+ r = session.execute(s)
+ data = json.loads(r.fetchone()['data'])
+ self.assertEqual(len(data['roles']), 1)
+ self.assertIn({'id': role_list[4]['id']}, data['roles'])
+ self.assertIn('other', data)
+
+ # Now add an entry that has one regular and one inherited role
+ role_grant = {'user_id': user['id'],
+ 'domain_id': domain2['id'],
+ 'data': json.dumps(
+ {'roles': [{'id': role_list[5]['id']},
+ {'id': role_list[6]['id'],
+ 'inherited_to': 'projects'}]})}
+ session.execute(user_domain_metadata_table.insert().values(role_grant))
+
+ session.commit()
+ self.downgrade(28)
+
+ s = sqlalchemy.select([user_project_metadata_table.c.data]).where(
+ (user_project_metadata_table.c.user_id == user['id']) &
+ (user_project_metadata_table.c.project_id == project['id']))
+ r = session.execute(s)
+ data = json.loads(r.fetchone()['data'])
+ self.assertEqual(len(data['roles']), 1)
+ self.assertIn(role_list[0]['id'], data['roles'])
+
+ s = sqlalchemy.select([user_project_metadata_table.c.data]).where(
+ (user_project_metadata_table.c.user_id == user['id']) &
+ (user_project_metadata_table.c.project_id == project2['id']))
+ r = session.execute(s)
+ data = json.loads(r.fetchone()['data'])
+ self.assertEqual(len(data['roles']), 1)
+ self.assertIn(role_list[1]['id'], data['roles'])
+
+ s = sqlalchemy.select([group_project_metadata_table.c.data]).where(
+ (group_project_metadata_table.c.group_id == group['id']) &
+ (group_project_metadata_table.c.project_id == project2['id']))
+ r = session.execute(s)
+ data = json.loads(r.fetchone()['data'])
+ self.assertEqual(len(data['roles']), 1)
+ self.assertIn(role_list[2]['id'], data['roles'])
+
+ s = sqlalchemy.select([user_domain_metadata_table.c.data]).where(
+ (user_domain_metadata_table.c.user_id == user['id']) &
+ (user_domain_metadata_table.c.domain_id == domain['id']))
+ r = session.execute(s)
+ data = json.loads(r.fetchone()['data'])
+ self.assertEqual(len(data['roles']), 1)
+ self.assertIn(role_list[3]['id'], data['roles'])
+
+ s = sqlalchemy.select([group_domain_metadata_table.c.data]).where(
+ (group_domain_metadata_table.c.group_id == group['id']) &
+ (group_domain_metadata_table.c.domain_id == domain['id']))
+ r = session.execute(s)
+ data = json.loads(r.fetchone()['data'])
+ self.assertEqual(len(data['roles']), 1)
+ self.assertIn(role_list[4]['id'], data['roles'])
+ self.assertIn('other', data)
+
+ # For user-domain2, where we had one regular and one inherited role,
+ # only the direct role should remain, the inherited role should
+ # have been deleted during the downgrade
+ s = sqlalchemy.select([user_domain_metadata_table.c.data]).where(
+ (user_domain_metadata_table.c.user_id == user['id']) &
+ (user_domain_metadata_table.c.domain_id == domain2['id']))
+ r = session.execute(s)
+ data = json.loads(r.fetchone()['data'])
+ self.assertEqual(len(data['roles']), 1)
+ self.assertIn(role_list[5]['id'], data['roles'])
+
+ def test_drop_credential_constraint(self):
+ ec2_credential = {
+ 'id': '100',
+ 'user_id': 'foo',
+ 'project_id': 'bar',
+ 'type': 'ec2',
+ 'blob': json.dumps({
+ "access": "12345",
+ "secret": "12345"
+ })
+ }
+ user = {
+ 'id': 'foo',
+ 'name': 'FOO',
+ 'password': 'foo2',
+ 'enabled': True,
+ 'email': 'foo@bar.com',
+ 'extra': json.dumps({'enabled': True})
+ }
+ tenant = {
+ 'id': 'bar',
+ 'name': 'BAR',
+ 'description': 'description',
+ 'enabled': True,
+ 'extra': json.dumps({'enabled': True})
+ }
+ session = self.Session()
+ self.upgrade(7)
+ self.insert_dict(session, 'user', user)
+ self.insert_dict(session, 'tenant', tenant)
+ self.insert_dict(session, 'credential', ec2_credential)
+ session.commit()
+ self.upgrade(30)
+ cred_table = sqlalchemy.Table('credential',
+ self.metadata,
+ autoload=True)
+ cred = session.query(cred_table).filter("id='100'").one()
+ self.assertEqual(cred.user_id,
+ ec2_credential['user_id'])
+
def populate_user_table(self, with_pass_enab=False,
with_pass_enab_domain=False):
# Populate the appropriate fields in the user
@@ -956,3 +1327,26 @@ class SqlUpgradeTests(test.TestCase):
for ver, change in changeset:
self.schema.runchange(ver, change, changeset.step)
self.assertEqual(self.schema.version, version)
+
+ def _mysql_check_all_tables_innodb(self):
+ database = self.engine.url.database
+
+ connection = self.engine.connect()
+ # sanity check
+ total = connection.execute("SELECT count(*) "
+ "from information_schema.TABLES "
+ "where TABLE_SCHEMA='%(database)s'" %
+ locals())
+ self.assertTrue(total.scalar() > 0, "No tables found. Wrong schema?")
+
+ noninnodb = connection.execute("SELECT table_name "
+ "from information_schema.TABLES "
+ "where TABLE_SCHEMA='%(database)s' "
+ "and ENGINE!='InnoDB' "
+ "and TABLE_NAME!='migrate_version'" %
+ locals())
+ names = [x[0] for x in noninnodb]
+ self.assertEqual(names, [],
+ "Non-InnoDB tables exist")
+
+ connection.close()
diff --git a/tests/test_token_bind.py b/tests/test_token_bind.py
new file mode 100644
index 00000000..20488a91
--- /dev/null
+++ b/tests/test_token_bind.py
@@ -0,0 +1,182 @@
+# Copyright 2013 OpenStack LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from keystone.common import wsgi
+from keystone import config
+from keystone import exception
+from keystone import test
+
+CONF = config.CONF
+
+KERBEROS_BIND = 'USER@REALM'
+
+# the only thing the function checks for is the presence of bind
+TOKEN_BIND_KERB = {'bind': {'kerberos': KERBEROS_BIND}}
+TOKEN_BIND_UNKNOWN = {'bind': {'FOO': 'BAR'}}
+TOKEN_BIND_NONE = {}
+
+ANY = 'any'
+ALL_TOKENS = [TOKEN_BIND_KERB, TOKEN_BIND_UNKNOWN, TOKEN_BIND_NONE]
+
+
+class BindTest(test.TestCase):
+ """Test binding tokens to a Principal.
+
+ Even though everything in this file references kerberos the same concepts
+ will apply to all future binding mechanisms.
+ """
+
+ def assert_kerberos_bind(self, tokens, bind_level,
+ use_kerberos=True, success=True):
+ if not isinstance(tokens, dict):
+ for token in tokens:
+ self.assert_kerberos_bind(token, bind_level,
+ use_kerberos=use_kerberos,
+ success=success)
+ elif use_kerberos == ANY:
+ for val in (True, False):
+ self.assert_kerberos_bind(tokens, bind_level,
+ use_kerberos=val, success=success)
+ else:
+ context = {}
+ CONF.token.enforce_token_bind = bind_level
+
+ if use_kerberos:
+ context['REMOTE_USER'] = KERBEROS_BIND
+ context['AUTH_TYPE'] = 'Negotiate'
+
+ if not success:
+ self.assertRaises(exception.Unauthorized,
+ wsgi.validate_token_bind,
+ context, tokens)
+ else:
+ wsgi.validate_token_bind(context, tokens)
+
+ # DISABLED
+
+ def test_bind_disabled_with_kerb_user(self):
+ self.assert_kerberos_bind(ALL_TOKENS,
+ bind_level='disabled',
+ use_kerberos=ANY,
+ success=True)
+
+ # PERMISSIVE
+
+ def test_bind_permissive_with_kerb_user(self):
+ self.assert_kerberos_bind(TOKEN_BIND_KERB,
+ bind_level='permissive',
+ use_kerberos=True,
+ success=True)
+
+ def test_bind_permissive_with_regular_token(self):
+ self.assert_kerberos_bind(TOKEN_BIND_NONE,
+ bind_level='permissive',
+ use_kerberos=ANY,
+ success=True)
+
+ def test_bind_permissive_without_kerb_user(self):
+ self.assert_kerberos_bind(TOKEN_BIND_KERB,
+ bind_level='permissive',
+ use_kerberos=False,
+ success=False)
+
+ def test_bind_permissive_with_unknown_bind(self):
+ self.assert_kerberos_bind(TOKEN_BIND_UNKNOWN,
+ bind_level='permissive',
+ use_kerberos=ANY,
+ success=True)
+
+ # STRICT
+
+ def test_bind_strict_with_regular_token(self):
+ self.assert_kerberos_bind(TOKEN_BIND_NONE,
+ bind_level='strict',
+ use_kerberos=ANY,
+ success=True)
+
+ def test_bind_strict_with_kerb_user(self):
+ self.assert_kerberos_bind(TOKEN_BIND_KERB,
+ bind_level='strict',
+ use_kerberos=True,
+ success=True)
+
+ def test_bind_strict_without_kerb_user(self):
+ self.assert_kerberos_bind(TOKEN_BIND_KERB,
+ bind_level='strict',
+ use_kerberos=False,
+ success=False)
+
+ def test_bind_strict_with_unknown_bind(self):
+ self.assert_kerberos_bind(TOKEN_BIND_UNKNOWN,
+ bind_level='strict',
+ use_kerberos=ANY,
+ success=False)
+
+ # REQUIRED
+
+ def test_bind_required_with_regular_token(self):
+ self.assert_kerberos_bind(TOKEN_BIND_NONE,
+ bind_level='required',
+ use_kerberos=ANY,
+ success=False)
+
+ def test_bind_required_with_kerb_user(self):
+ self.assert_kerberos_bind(TOKEN_BIND_KERB,
+ bind_level='required',
+ use_kerberos=True,
+ success=True)
+
+ def test_bind_required_without_kerb_user(self):
+ self.assert_kerberos_bind(TOKEN_BIND_KERB,
+ bind_level='required',
+ use_kerberos=False,
+ success=False)
+
+ def test_bind_required_with_unknown_bind(self):
+ self.assert_kerberos_bind(TOKEN_BIND_UNKNOWN,
+ bind_level='required',
+ use_kerberos=ANY,
+ success=False)
+
+ # NAMED
+
+ def test_bind_named_with_regular_token(self):
+ self.assert_kerberos_bind(TOKEN_BIND_NONE,
+ bind_level='kerberos',
+ use_kerberos=ANY,
+ success=False)
+
+ def test_bind_named_with_kerb_user(self):
+ self.assert_kerberos_bind(TOKEN_BIND_KERB,
+ bind_level='kerberos',
+ use_kerberos=True,
+ success=True)
+
+ def test_bind_named_without_kerb_user(self):
+ self.assert_kerberos_bind(TOKEN_BIND_KERB,
+ bind_level='kerberos',
+ use_kerberos=False,
+ success=False)
+
+ def test_bind_named_with_unknown_bind(self):
+ self.assert_kerberos_bind(TOKEN_BIND_UNKNOWN,
+ bind_level='kerberos',
+ use_kerberos=ANY,
+ success=False)
+
+ def test_bind_named_with_unknown_scheme(self):
+ self.assert_kerberos_bind(ALL_TOKENS,
+ bind_level='unknown',
+ use_kerberos=ANY,
+ success=False)
diff --git a/tests/test_token_provider.py b/tests/test_token_provider.py
new file mode 100644
index 00000000..a7e92717
--- /dev/null
+++ b/tests/test_token_provider.py
@@ -0,0 +1,439 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 OpenStack LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import uuid
+
+from keystone import exception
+from keystone import test
+from keystone import token
+
+
+SAMPLE_V2_TOKEN = {
+ "access": {
+ "trust": {
+ "id": "abc123",
+ "trustee_user_id": "123456"
+ },
+ "serviceCatalog": [
+ {
+ "endpoints": [
+ {
+ "adminURL": "http://localhost:8774/v1.1/01257",
+ "id": "51934fe63a5b4ac0a32664f64eb462c3",
+ "internalURL": "http://localhost:8774/v1.1/01257",
+ "publicURL": "http://localhost:8774/v1.1/01257",
+ "region": "RegionOne"
+ }
+ ],
+ "endpoints_links": [],
+ "name": "nova",
+ "type": "compute"
+ },
+ {
+ "endpoints": [
+ {
+ "adminURL": "http://localhost:9292",
+ "id": "aaa17a539e364297a7845d67c7c7cc4b",
+ "internalURL": "http://localhost:9292",
+ "publicURL": "http://localhost:9292",
+ "region": "RegionOne"
+ }
+ ],
+ "endpoints_links": [],
+ "name": "glance",
+ "type": "image"
+ },
+ {
+ "endpoints": [
+ {
+ "adminURL": "http://localhost:8776/v1/01257",
+ "id": "077d82df25304abeac2294004441db5a",
+ "internalURL": "http://localhost:8776/v1/01257",
+ "publicURL": "http://localhost:8776/v1/01257",
+ "region": "RegionOne"
+ }
+ ],
+ "endpoints_links": [],
+ "name": "volume",
+ "type": "volume"
+ },
+ {
+ "endpoints": [
+ {
+ "adminURL": "http://localhost:8773/services/Admin",
+ "id": "b06997fd08414903ad458836efaa9067",
+ "internalURL": "http://localhost:8773/services/Cloud",
+ "publicURL": "http://localhost:8773/services/Cloud",
+ "region": "RegionOne"
+ }
+ ],
+ "endpoints_links": [],
+ "name": "ec2",
+ "type": "ec2"
+ },
+ {
+ "endpoints": [
+ {
+ "adminURL": "http://localhost:8888/v1",
+ "id": "7bd0c643e05a4a2ab40902b2fa0dd4e6",
+ "internalURL": "http://localhost:8888/v1/AUTH_01257",
+ "publicURL": "http://localhost:8888/v1/AUTH_01257",
+ "region": "RegionOne"
+ }
+ ],
+ "endpoints_links": [],
+ "name": "swift",
+ "type": "object-store"
+ },
+ {
+ "endpoints": [
+ {
+ "adminURL": "http://localhost:35357/v2.0",
+ "id": "02850c5d1d094887bdc46e81e1e15dc7",
+ "internalURL": "http://localhost:5000/v2.0",
+ "publicURL": "http://localhost:5000/v2.0",
+ "region": "RegionOne"
+ }
+ ],
+ "endpoints_links": [],
+ "name": "keystone",
+ "type": "identity"
+ }
+ ],
+ "token": {
+ "expires": "2013-05-22T00:02:43.941430Z",
+ "id": "ce4fc2d36eea4cc9a36e666ac2f1029a",
+ "issued_at": "2013-05-21T00:02:43.941473Z",
+ "tenant": {
+ "enabled": True,
+ "id": "01257",
+ "name": "service"
+ }
+ },
+ "user": {
+ "id": "f19ddbe2c53c46f189fe66d0a7a9c9ce",
+ "name": "nova",
+ "roles": [
+ {
+ "name": "_member_"
+ },
+ {
+ "name": "admin"
+ }
+ ],
+ "roles_links": [],
+ "username": "nova"
+ }
+ }
+}
+
+SAMPLE_V3_TOKEN = {
+ "token": {
+ "catalog": [
+ {
+ "endpoints": [
+ {
+ "id": "02850c5d1d094887bdc46e81e1e15dc7",
+ "interface": "admin",
+ "region": "RegionOne",
+ "url": "http://localhost:35357/v2.0"
+ },
+ {
+ "id": "446e244b75034a9ab4b0811e82d0b7c8",
+ "interface": "internal",
+ "region": "RegionOne",
+ "url": "http://localhost:5000/v2.0"
+ },
+ {
+ "id": "47fa3d9f499240abb5dfcf2668f168cd",
+ "interface": "public",
+ "region": "RegionOne",
+ "url": "http://localhost:5000/v2.0"
+ }
+ ],
+ "id": "26d7541715a44a4d9adad96f9872b633",
+ "type": "identity",
+ },
+ {
+ "endpoints": [
+ {
+ "id": "aaa17a539e364297a7845d67c7c7cc4b",
+ "interface": "admin",
+ "region": "RegionOne",
+ "url": "http://localhost:9292"
+ },
+ {
+ "id": "4fa9620e42394cb1974736dce0856c71",
+ "interface": "internal",
+ "region": "RegionOne",
+ "url": "http://localhost:9292"
+ },
+ {
+ "id": "9673687f9bc441d88dec37942bfd603b",
+ "interface": "public",
+ "region": "RegionOne",
+ "url": "http://localhost:9292"
+ }
+ ],
+ "id": "d27a41843f4e4b0e8cf6dac4082deb0d",
+ "type": "image",
+ },
+ {
+ "endpoints": [
+ {
+ "id": "7bd0c643e05a4a2ab40902b2fa0dd4e6",
+ "interface": "admin",
+ "region": "RegionOne",
+ "url": "http://localhost:8888/v1"
+ },
+ {
+ "id": "43bef154594d4ccb8e49014d20624e1d",
+ "interface": "internal",
+ "region": "RegionOne",
+ "url": "http://localhost:8888/v1/AUTH_01257"
+ },
+ {
+ "id": "e63b5f5d7aa3493690189d0ff843b9b3",
+ "interface": "public",
+ "region": "RegionOne",
+ "url": "http://localhost:8888/v1/AUTH_01257"
+ }
+ ],
+ "id": "a669e152f1104810a4b6701aade721bb",
+ "type": "object-store",
+ },
+ {
+ "endpoints": [
+ {
+ "id": "51934fe63a5b4ac0a32664f64eb462c3",
+ "interface": "admin",
+ "region": "RegionOne",
+ "url": "http://localhost:8774/v1.1/01257"
+ },
+ {
+ "id": "869b535eea0d42e483ae9da0d868ebad",
+ "interface": "internal",
+ "region": "RegionOne",
+ "url": "http://localhost:8774/v1.1/01257"
+ },
+ {
+ "id": "93583824c18f4263a2245ca432b132a6",
+ "interface": "public",
+ "region": "RegionOne",
+ "url": "http://localhost:8774/v1.1/01257"
+ }
+ ],
+ "id": "7f32cc2af6c9476e82d75f80e8b3bbb8",
+ "type": "compute",
+ },
+ {
+ "endpoints": [
+ {
+ "id": "b06997fd08414903ad458836efaa9067",
+ "interface": "admin",
+ "region": "RegionOne",
+ "url": "http://localhost:8773/services/Admin"
+ },
+ {
+ "id": "411f7de7c9a8484c9b46c254fb2676e2",
+ "interface": "internal",
+ "region": "RegionOne",
+ "url": "http://localhost:8773/services/Cloud"
+ },
+ {
+ "id": "f21c93f3da014785854b4126d0109c49",
+ "interface": "public",
+ "region": "RegionOne",
+ "url": "http://localhost:8773/services/Cloud"
+ }
+ ],
+ "id": "b08c9c7d4ef543eba5eeb766f72e5aa1",
+ "type": "ec2",
+ },
+ {
+ "endpoints": [
+ {
+ "id": "077d82df25304abeac2294004441db5a",
+ "interface": "admin",
+ "region": "RegionOne",
+ "url": "http://localhost:8776/v1/01257"
+ },
+ {
+ "id": "875bf282362c40219665278b4fd11467",
+ "interface": "internal",
+ "region": "RegionOne",
+ "url": "http://localhost:8776/v1/01257"
+ },
+ {
+ "id": "cd229aa6df0640dc858a8026eb7e640c",
+ "interface": "public",
+ "region": "RegionOne",
+ "url": "http://localhost:8776/v1/01257"
+ }
+ ],
+ "id": "5db21b82617f4a95816064736a7bec22",
+ "type": "volume",
+ }
+ ],
+ "expires_at": "2013-05-22T00:02:43.941430Z",
+ "issued_at": "2013-05-21T00:02:43.941473Z",
+ "methods": [
+ "password"
+ ],
+ "project": {
+ "domain": {
+ "id": "default",
+ "name": "Default"
+ },
+ "id": "01257",
+ "name": "service"
+ },
+ "roles": [
+ {
+ "id": "9fe2ff9ee4384b1894a90878d3e92bab",
+ "name": "_member_"
+ },
+ {
+ "id": "53bff13443bd4450b97f978881d47b18",
+ "name": "admin"
+ }
+ ],
+ "user": {
+ "domain": {
+ "id": "default",
+ "name": "Default"
+ },
+ "id": "f19ddbe2c53c46f189fe66d0a7a9c9ce",
+ "name": "nova"
+ },
+ "OS-TRUST:trust": {
+ "id": "abc123",
+ "trustee_user_id": "123456",
+ "trustor_user_id": "333333",
+ "impersonation": False
+ }
+ }
+}
+
+
+class TestTokenProvider(test.TestCase):
+ def setUp(self):
+ super(TestTokenProvider, self).setUp()
+ self.load_backends()
+
+ def test_get_token_version(self):
+ self.assertEqual(
+ token.provider.V2,
+ self.token_provider_api.get_token_version(SAMPLE_V2_TOKEN))
+ self.assertEqual(
+ token.provider.V3,
+ self.token_provider_api.get_token_version(SAMPLE_V3_TOKEN))
+ self.assertRaises(token.provider.UnsupportedTokenVersionException,
+ self.token_provider_api.get_token_version,
+ 'bogus')
+
+ def test_issue_token(self):
+ self.assertRaises(token.provider.UnsupportedTokenVersionException,
+ self.token_provider_api.issue_token,
+ 'bogus_version')
+
+ def test_validate_token(self):
+ self.assertRaises(token.provider.UnsupportedTokenVersionException,
+ self.token_provider_api.validate_token,
+ uuid.uuid4().hex,
+ None,
+ 'bogus_version')
+
+ def test_token_format_provider_mismatch(self):
+ self.opt_in_group('signing', token_format='UUID')
+ self.opt_in_group('token',
+ provider=token.provider.PKI_PROVIDER)
+ try:
+ token.provider.Manager()
+ raise Exception(
+ 'expecting ValueError on token provider misconfiguration')
+ except exception.UnexpectedError:
+ pass
+
+ self.opt_in_group('signing', token_format='PKI')
+ self.opt_in_group('token',
+ provider=token.provider.UUID_PROVIDER)
+ try:
+ token.provider.Manager()
+ raise Exception(
+ 'expecting ValueError on token provider misconfiguration')
+ except exception.UnexpectedError:
+ pass
+
+ # should be OK as token_format and provider aligns
+ self.opt_in_group('signing', token_format='PKI')
+ self.opt_in_group('token',
+ provider=token.provider.PKI_PROVIDER)
+ token.provider.Manager()
+
+ self.opt_in_group('signing', token_format='UUID')
+ self.opt_in_group('token',
+ provider=token.provider.UUID_PROVIDER)
+ token.provider.Manager()
+
+ # custom provider should be OK too
+ self.opt_in_group('signing', token_format='CUSTOM')
+ self.opt_in_group('token',
+ provider=token.provider.PKI_PROVIDER)
+ token.provider.Manager()
+
+ def test_default_token_format(self):
+ self.assertEqual(token.provider.Manager.get_token_provider(),
+ token.provider.PKI_PROVIDER)
+
+ def test_uuid_token_format_and_no_provider(self):
+ self.opt_in_group('signing', token_format='UUID')
+ self.assertEqual(token.provider.Manager.get_token_provider(),
+ token.provider.UUID_PROVIDER)
+
+ def test_unsupported_token_format(self):
+ self.opt_in_group('signing', token_format='CUSTOM')
+ self.assertRaises(exception.UnexpectedError,
+ token.provider.Manager.get_token_provider)
+
+ def test_uuid_provider(self):
+ self.opt_in_group('token', provider=token.provider.UUID_PROVIDER)
+ self.assertEqual(token.provider.Manager.get_token_provider(),
+ token.provider.UUID_PROVIDER)
+
+ def test_provider_override_token_format(self):
+ self.opt_in_group('token',
+ provider='keystone.token.providers.pki.Test')
+ self.assertEqual(token.provider.Manager.get_token_provider(),
+ 'keystone.token.providers.pki.Test')
+
+ self.opt_in_group('signing', token_format='UUID')
+ self.opt_in_group('token',
+ provider=token.provider.UUID_PROVIDER)
+ self.assertEqual(token.provider.Manager.get_token_provider(),
+ token.provider.UUID_PROVIDER)
+
+ self.opt_in_group('signing', token_format='PKI')
+ self.opt_in_group('token',
+ provider=token.provider.PKI_PROVIDER)
+ self.assertEqual(token.provider.Manager.get_token_provider(),
+ token.provider.PKI_PROVIDER)
+
+ self.opt_in_group('signing', token_format='CUSTOM')
+ self.opt_in_group('token',
+ provider='my.package.MyProvider')
+ self.assertEqual(token.provider.Manager.get_token_provider(),
+ 'my.package.MyProvider')
diff --git a/tests/test_uuid_token_provider.conf b/tests/test_uuid_token_provider.conf
new file mode 100644
index 00000000..d127ea3b
--- /dev/null
+++ b/tests/test_uuid_token_provider.conf
@@ -0,0 +1,2 @@
+[token]
+provider = keystone.token.providers.uuid.Provider
diff --git a/tests/test_v3.py b/tests/test_v3.py
index 93293b6c..4f00de7d 100644
--- a/tests/test_v3.py
+++ b/tests/test_v3.py
@@ -8,7 +8,6 @@ from keystone import test
from keystone import auth
from keystone.common import serializer
-from keystone.common.sql import util as sql_util
from keystone import config
from keystone.openstack.common import timeutils
from keystone.policy.backends import rules
@@ -23,6 +22,15 @@ TIME_FORMAT = '%Y-%m-%dT%H:%M:%S.%fZ'
class RestfulTestCase(test_content_types.RestfulTestCase):
+ _config_file_list = [test.etcdir('keystone.conf.sample'),
+ test.testsdir('test_overrides.conf'),
+ test.testsdir('backend_sql.conf'),
+ test.testsdir('backend_sql_disk.conf')]
+
+ #override this to sepcify the complete list of configuration files
+ def config_files(self):
+ return self._config_file_list
+
def setUp(self, load_sample_data=True):
"""Setup for v3 Restful Test Cases.
@@ -31,13 +39,9 @@ class RestfulTestCase(test_content_types.RestfulTestCase):
load_sample_data should be set to false.
"""
- self.config([
- test.etcdir('keystone.conf.sample'),
- test.testsdir('test_overrides.conf'),
- test.testsdir('backend_sql.conf'),
- test.testsdir('backend_sql_disk.conf')])
+ self.config(self.config_files())
- sql_util.setup_test_database()
+ test.setup_test_database()
self.load_backends()
self.public_app = webtest.TestApp(
@@ -102,7 +106,7 @@ class RestfulTestCase(test_content_types.RestfulTestCase):
self.admin_server.kill()
self.public_server = None
self.admin_server = None
- sql_util.teardown_test_database()
+ test.teardown_test_database()
# need to reset the plug-ins
auth.controllers.AUTH_METHODS = {}
#drop the policy rules
@@ -331,7 +335,7 @@ class RestfulTestCase(test_content_types.RestfulTestCase):
links['previous'])
def assertValidListResponse(self, resp, key, entity_validator, ref=None,
- expected_length=None):
+ expected_length=None, keys_to_check=None):
"""Make assertions common to all API list responses.
If a reference is provided, it's ID will be searched for in the
@@ -352,11 +356,12 @@ class RestfulTestCase(test_content_types.RestfulTestCase):
for entity in entities:
self.assertIsNotNone(entity)
- self.assertValidEntity(entity)
+ self.assertValidEntity(entity, keys_to_check=keys_to_check)
entity_validator(entity)
if ref:
entity = [x for x in entities if x['id'] == ref['id']][0]
- self.assertValidEntity(entity, ref)
+ self.assertValidEntity(entity, ref=ref,
+ keys_to_check=keys_to_check)
entity_validator(entity, ref)
return entities
@@ -365,17 +370,21 @@ class RestfulTestCase(test_content_types.RestfulTestCase):
"""Make assertions common to all API responses."""
entity = resp.result.get(key)
self.assertIsNotNone(entity)
- self.assertValidEntity(entity, *args, **kwargs)
+ keys = kwargs.pop('keys_to_check', None)
+ self.assertValidEntity(entity, keys_to_check=keys, *args, **kwargs)
entity_validator(entity, *args, **kwargs)
return entity
- def assertValidEntity(self, entity, ref=None):
+ def assertValidEntity(self, entity, ref=None, keys_to_check=None):
"""Make assertions common to all API entities.
If a reference is provided, the entity will also be compared against
the reference.
"""
- keys = ['name', 'description', 'enabled']
+ if keys_to_check:
+ keys = keys_to_check
+ else:
+ keys = ['name', 'description', 'enabled']
for k in ['id'] + keys:
msg = '%s unexpectedly None in %s' % (k, entity)
@@ -439,9 +448,14 @@ class RestfulTestCase(test_content_types.RestfulTestCase):
return token
def assertValidScopedTokenResponse(self, r, *args, **kwargs):
+ require_catalog = kwargs.pop('require_catalog', True)
token = self.assertValidTokenResponse(r, *args, **kwargs)
- self.assertIn('catalog', token)
+ if require_catalog:
+ self.assertIn('catalog', token)
+ else:
+ self.assertNotIn('catalog', token)
+
self.assertIn('roles', token)
self.assertTrue(token['roles'])
for role in token['roles']:
@@ -698,6 +712,7 @@ class RestfulTestCase(test_content_types.RestfulTestCase):
resp,
'roles',
self.assertValidRole,
+ keys_to_check=['name'],
*args,
**kwargs)
@@ -706,6 +721,7 @@ class RestfulTestCase(test_content_types.RestfulTestCase):
resp,
'role',
self.assertValidRole,
+ keys_to_check=['name'],
*args,
**kwargs)
@@ -715,6 +731,87 @@ class RestfulTestCase(test_content_types.RestfulTestCase):
self.assertEqual(ref['name'], entity['name'])
return entity
+ def assertValidRoleAssignmentListResponse(self, resp, ref=None,
+ expected_length=None):
+
+ entities = resp.result.get('role_assignments')
+
+ if expected_length is not None:
+ self.assertEqual(len(entities), expected_length)
+ elif ref is not None:
+ # we're at least expecting the ref
+ self.assertNotEmpty(entities)
+
+ # collections should have relational links
+ self.assertValidListLinks(resp.result.get('links'))
+
+ for entity in entities:
+ self.assertIsNotNone(entity)
+ self.assertValidRoleAssignment(entity)
+ if ref:
+ self.assertValidRoleAssignment(entity, ref)
+ return entities
+
+ def assertValidRoleAssignment(self, entity, ref=None, url=None):
+ self.assertIsNotNone(entity.get('role'))
+ self.assertIsNotNone(entity.get('scope'))
+
+ # Only one of user or group should be present
+ self.assertIsNotNone(entity.get('user') or
+ entity.get('group'))
+ self.assertIsNone(entity.get('user') and
+ entity.get('group'))
+
+ # Only one of domain or project should be present
+ self.assertIsNotNone(entity['scope'].get('project') or
+ entity['scope'].get('domain'))
+ self.assertIsNone(entity['scope'].get('project') and
+ entity['scope'].get('domain'))
+
+ if entity['scope'].get('project'):
+ self.assertIsNotNone(entity['scope']['project'].get('id'))
+ else:
+ self.assertIsNotNone(entity['scope']['domain'].get('id'))
+ self.assertIsNotNone(entity.get('links'))
+ self.assertIsNotNone(entity['links'].get('assignment'))
+
+ if ref:
+ if ref.get('user'):
+ self.assertEqual(ref['user']['id'], entity['user']['id'])
+ if ref.get('group'):
+ self.assertEqual(ref['group']['id'], entity['group']['id'])
+ if ref.get('role'):
+ self.assertEqual(ref['role']['id'], entity['role']['id'])
+ if ref['scope'].get('project'):
+ self.assertEqual(ref['scope']['project']['id'],
+ entity['scope']['project']['id'])
+ if ref['scope'].get('domain'):
+ self.assertEqual(ref['scope']['domain']['id'],
+ entity['scope']['domain']['id'])
+ if url:
+ self.assertIn(url, entity['links']['assignment'])
+
+ def assertRoleAssignmentInListResponse(
+ self, resp, ref, link_url=None, expected=1):
+
+ found_count = 0
+ for entity in resp.result.get('role_assignments'):
+ try:
+ self.assertValidRoleAssignment(
+ entity, ref=ref, url=link_url)
+ except Exception:
+ # It doesn't match, so let's go onto the next one
+ pass
+ else:
+ found_count += 1
+ self.assertEqual(found_count, expected)
+
+ def assertRoleAssignmentNotInListResponse(
+ self, resp, ref, link_url=None):
+
+ self.assertRoleAssignmentInListResponse(
+ resp, ref=ref, link_url=link_url, expected=0)
+
# policy validation
def assertValidPolicyListResponse(self, resp, *args, **kwargs):
diff --git a/tests/test_v3_auth.py b/tests/test_v3_auth.py
index a2bee8b8..11d66700 100644
--- a/tests/test_v3_auth.py
+++ b/tests/test_v3_auth.py
@@ -15,12 +15,11 @@
import json
import uuid
-import nose.exc
-
from keystone import auth
from keystone.common import cms
from keystone import config
from keystone import exception
+from keystone import test
import test_v3
@@ -96,9 +95,14 @@ class TestAuthInfo(test_v3.RestfulTestCase):
method_name)
-class TestTokenAPIs(test_v3.RestfulTestCase):
+class TestPKITokenAPIs(test_v3.RestfulTestCase):
+ def config_files(self):
+ conf_files = super(TestPKITokenAPIs, self).config_files()
+ conf_files.append(test.testsdir('test_pki_token_provider.conf'))
+ return conf_files
+
def setUp(self):
- super(TestTokenAPIs, self).setUp()
+ super(TestPKITokenAPIs, self).setUp()
auth_data = self.build_authentication_request(
username=self.user['name'],
user_domain_id=self.domain_id,
@@ -111,8 +115,7 @@ class TestTokenAPIs(test_v3.RestfulTestCase):
def test_default_fixture_scope_token(self):
self.assertIsNotNone(self.get_scoped_token())
- def test_v3_pki_token_id(self):
- self.opt_in_group('signing', token_format='PKI')
+ def test_v3_token_id(self):
auth_data = self.build_authentication_request(
user_id=self.user['id'],
password=self.user['password'])
@@ -120,13 +123,19 @@ class TestTokenAPIs(test_v3.RestfulTestCase):
token_data = resp.result
token_id = resp.headers.get('X-Subject-Token')
self.assertIn('expires_at', token_data['token'])
- token_signed = cms.cms_sign_token(json.dumps(token_data),
- CONF.signing.certfile,
- CONF.signing.keyfile)
- self.assertEqual(token_signed, token_id)
+
+ expected_token_id = cms.cms_sign_token(json.dumps(token_data),
+ CONF.signing.certfile,
+ CONF.signing.keyfile)
+ self.assertEqual(expected_token_id, token_id)
+ # should be able to validate hash PKI token as well
+ hash_token_id = cms.cms_hash_token(token_id)
+ headers = {'X-Subject-Token': hash_token_id}
+ resp = self.get('/auth/tokens', headers=headers)
+ expected_token_data = resp.result
+ self.assertDictEqual(expected_token_data, token_data)
def test_v3_v2_intermix_non_default_domain_failed(self):
- self.opt_in_group('signing', token_format='UUID')
auth_data = self.build_authentication_request(
user_id=self.user['id'],
password=self.user['password'])
@@ -141,7 +150,6 @@ class TestTokenAPIs(test_v3.RestfulTestCase):
expected_status=401)
def test_v3_v2_intermix_domain_scoped_token_failed(self):
- self.opt_in_group('signing', token_format='UUID')
# grant the domain role to user
path = '/domains/%s/users/%s/roles/%s' % (
self.domain['id'], self.user['id'], self.role['id'])
@@ -175,30 +183,7 @@ class TestTokenAPIs(test_v3.RestfulTestCase):
method='GET',
expected_status=401)
- def test_v3_v2_unscoped_uuid_token_intermix(self):
- self.opt_in_group('signing', token_format='UUID')
- auth_data = self.build_authentication_request(
- user_id=self.default_domain_user['id'],
- password=self.default_domain_user['password'])
- resp = self.post('/auth/tokens', body=auth_data)
- token_data = resp.result
- token = resp.headers.get('X-Subject-Token')
-
- # now validate the v3 token with v2 API
- path = '/v2.0/tokens/%s' % (token)
- resp = self.admin_request(path=path,
- token='ADMIN',
- method='GET')
- v2_token = resp.result
- self.assertEqual(v2_token['access']['user']['id'],
- token_data['token']['user']['id'])
- # v2 token time has not fraction of second precision so
- # just need to make sure the non fraction part agrees
- self.assertIn(v2_token['access']['token']['expires'][:-1],
- token_data['token']['expires_at'])
-
- def test_v3_v2_unscoped_pki_token_intermix(self):
- self.opt_in_group('signing', token_format='PKI')
+ def test_v3_v2_unscoped_token_intermix(self):
auth_data = self.build_authentication_request(
user_id=self.default_domain_user['id'],
password=self.default_domain_user['password'])
@@ -219,10 +204,9 @@ class TestTokenAPIs(test_v3.RestfulTestCase):
self.assertIn(v2_token['access']['token']['expires'][:-1],
token_data['token']['expires_at'])
- def test_v3_v2_uuid_token_intermix(self):
+ def test_v3_v2_token_intermix(self):
# FIXME(gyee): PKI tokens are not interchangeable because token
# data is baked into the token itself.
- self.opt_in_group('signing', token_format='UUID')
auth_data = self.build_authentication_request(
user_id=self.default_domain_user['id'],
password=self.default_domain_user['password'],
@@ -246,10 +230,7 @@ class TestTokenAPIs(test_v3.RestfulTestCase):
self.assertEqual(v2_token['access']['user']['roles'][0]['id'],
token_data['token']['roles'][0]['id'])
- def test_v3_v2_pki_token_intermix(self):
- # FIXME(gyee): PKI tokens are not interchangeable because token
- # data is baked into the token itself.
- self.opt_in_group('signing', token_format='PKI')
+ def test_v3_v2_hashed_pki_token_intermix(self):
auth_data = self.build_authentication_request(
user_id=self.default_domain_user['id'],
password=self.default_domain_user['password'],
@@ -258,7 +239,8 @@ class TestTokenAPIs(test_v3.RestfulTestCase):
token_data = resp.result
token = resp.headers.get('X-Subject-Token')
- # now validate the v3 token with v2 API
+ # should be able to validate a hash PKI token in v2 too
+ token = cms.cms_hash_token(token)
path = '/v2.0/tokens/%s' % (token)
resp = self.admin_request(path=path,
token='ADMIN',
@@ -268,13 +250,12 @@ class TestTokenAPIs(test_v3.RestfulTestCase):
token_data['token']['user']['id'])
# v2 token time has not fraction of second precision so
# just need to make sure the non fraction part agrees
- self.assertIn(v2_token['access']['token']['expires'][-1],
+ self.assertIn(v2_token['access']['token']['expires'][:-1],
token_data['token']['expires_at'])
self.assertEqual(v2_token['access']['user']['roles'][0]['id'],
token_data['token']['roles'][0]['id'])
- def test_v2_v3_unscoped_uuid_token_intermix(self):
- self.opt_in_group('signing', token_format='UUID')
+ def test_v2_v3_unscoped_token_intermix(self):
body = {
'auth': {
'passwordCredentials': {
@@ -297,59 +278,7 @@ class TestTokenAPIs(test_v3.RestfulTestCase):
self.assertIn(v2_token_data['access']['token']['expires'][-1],
token_data['token']['expires_at'])
- def test_v2_v3_unscoped_pki_token_intermix(self):
- self.opt_in_group('signing', token_format='PKI')
- body = {
- 'auth': {
- 'passwordCredentials': {
- 'userId': self.user['id'],
- 'password': self.user['password']
- }
- }}
- resp = self.admin_request(path='/v2.0/tokens',
- method='POST',
- body=body)
- v2_token_data = resp.result
- v2_token = v2_token_data['access']['token']['id']
- headers = {'X-Subject-Token': v2_token}
- resp = self.get('/auth/tokens', headers=headers)
- token_data = resp.result
- self.assertEqual(v2_token_data['access']['user']['id'],
- token_data['token']['user']['id'])
- # v2 token time has not fraction of second precision so
- # just need to make sure the non fraction part agrees
- self.assertIn(v2_token_data['access']['token']['expires'][-1],
- token_data['token']['expires_at'])
-
- def test_v2_v3_uuid_token_intermix(self):
- self.opt_in_group('signing', token_format='UUID')
- body = {
- 'auth': {
- 'passwordCredentials': {
- 'userId': self.user['id'],
- 'password': self.user['password']
- },
- 'tenantId': self.project['id']
- }}
- resp = self.admin_request(path='/v2.0/tokens',
- method='POST',
- body=body)
- v2_token_data = resp.result
- v2_token = v2_token_data['access']['token']['id']
- headers = {'X-Subject-Token': v2_token}
- resp = self.get('/auth/tokens', headers=headers)
- token_data = resp.result
- self.assertEqual(v2_token_data['access']['user']['id'],
- token_data['token']['user']['id'])
- # v2 token time has not fraction of second precision so
- # just need to make sure the non fraction part agrees
- self.assertIn(v2_token_data['access']['token']['expires'][-1],
- token_data['token']['expires_at'])
- self.assertEqual(v2_token_data['access']['user']['roles'][0]['name'],
- token_data['token']['roles'][0]['name'])
-
- def test_v2_v3_pki_token_intermix(self):
- self.opt_in_group('signing', token_format='PKI')
+ def test_v2_v3_token_intermix(self):
body = {
'auth': {
'passwordCredentials': {
@@ -402,6 +331,28 @@ class TestTokenAPIs(test_v3.RestfulTestCase):
self.assertIn('signed', r.result)
+class TestUUIDTokenAPIs(TestPKITokenAPIs):
+ def config_files(self):
+ conf_files = super(TestUUIDTokenAPIs, self).config_files()
+ conf_files.append(test.testsdir('test_uuid_token_provider.conf'))
+ return conf_files
+
+ def test_v3_token_id(self):
+ auth_data = self.build_authentication_request(
+ user_id=self.user['id'],
+ password=self.user['password'])
+ resp = self.post('/auth/tokens', body=auth_data)
+ token_data = resp.result
+ token_id = resp.headers.get('X-Subject-Token')
+ self.assertIn('expires_at', token_data['token'])
+ self.assertFalse(cms.is_ans1_token(token_id))
+
+ def test_v3_v2_hashed_pki_token_intermix(self):
+ # this test is only applicable for PKI tokens
+ # skipping it for UUID tokens
+ pass
+
+
class TestTokenRevoking(test_v3.RestfulTestCase):
"""Test token revocation on the v3 Identity API."""
@@ -793,6 +744,66 @@ class TestTokenRevoking(test_v3.RestfulTestCase):
project_id=self.projectA['id']))
+class TestAuthExternalDisabled(test_v3.RestfulTestCase):
+ def config_files(self):
+ list = self._config_file_list[:]
+ list.append('auth_plugin_external_disabled.conf')
+ return list
+
+ def test_remote_user_disabled(self):
+ auth_data = self.build_authentication_request()['auth']
+ api = auth.controllers.Auth()
+ context = {'REMOTE_USER': '%s@%s' % (self.user['name'],
+ self.domain['id'])}
+ auth_info = auth.controllers.AuthInfo(None, auth_data)
+ auth_context = {'extras': {}, 'method_names': []}
+ self.assertRaises(exception.Unauthorized,
+ api.authenticate,
+ context,
+ auth_info,
+ auth_context)
+
+
+class TestAuthExternalDomain(test_v3.RestfulTestCase):
+ content_type = 'json'
+
+ def config_files(self):
+ list = self._config_file_list[:]
+ list.append('auth_plugin_external_domain.conf')
+ return list
+
+ def test_remote_user_with_realm(self):
+ auth_data = self.build_authentication_request()['auth']
+ api = auth.controllers.Auth()
+ context = {'REMOTE_USER': '%s@%s' %
+ (self.user['name'], self.domain['name'])}
+ auth_info = auth.controllers.AuthInfo(None, auth_data)
+ auth_context = {'extras': {}, 'method_names': []}
+ api.authenticate(context, auth_info, auth_context)
+ self.assertEqual(auth_context['user_id'], self.user['id'])
+
+ def test_project_id_scoped_with_remote_user(self):
+ CONF.token.bind = ['kerberos']
+ auth_data = self.build_authentication_request(
+ project_id=self.project['id'])
+ remote_user = '%s@%s' % (self.user['name'], self.domain['name'])
+ self.admin_app.extra_environ.update({'REMOTE_USER': remote_user,
+ 'AUTH_TYPE': 'Negotiate'})
+ r = self.post('/auth/tokens', body=auth_data)
+ token = self.assertValidProjectScopedTokenResponse(r)
+ self.assertEquals(token['bind']['kerberos'], self.user['name'])
+
+ def test_unscoped_bind_with_remote_user(self):
+ CONF.token.bind = ['kerberos']
+ auth_data = self.build_authentication_request()
+ remote_user = '%s@%s' % (self.user['name'], self.domain['name'])
+ self.admin_app.extra_environ.update({'REMOTE_USER': remote_user,
+ 'AUTH_TYPE': 'Negotiate'})
+ r = self.post('/auth/tokens', body=auth_data)
+ token = self.assertValidUnscopedTokenResponse(r)
+ self.assertEquals(token['bind']['kerberos'], self.user['name'])
+
+
class TestAuthJSON(test_v3.RestfulTestCase):
content_type = 'json'
@@ -855,6 +866,45 @@ class TestAuthJSON(test_v3.RestfulTestCase):
self.assertValidProjectScopedTokenResponse(r)
self.assertEqual(r.result['token']['project']['id'], project['id'])
+ def test_default_project_id_scoped_token_with_user_id_no_catalog(self):
+ # create a second project to work with
+ ref = self.new_project_ref(domain_id=self.domain_id)
+ r = self.post('/projects', body={'project': ref})
+ project = self.assertValidProjectResponse(r, ref)
+
+ # grant the user a role on the project
+ self.put(
+ '/projects/%(project_id)s/users/%(user_id)s/roles/%(role_id)s' % {
+ 'user_id': self.user['id'],
+ 'project_id': project['id'],
+ 'role_id': self.role['id']})
+
+ # set the user's preferred project
+ body = {'user': {'default_project_id': project['id']}}
+ r = self.patch('/users/%(user_id)s' % {
+ 'user_id': self.user['id']},
+ body=body)
+ self.assertValidUserResponse(r)
+
+ # attempt to authenticate without requesting a project
+ auth_data = self.build_authentication_request(
+ user_id=self.user['id'],
+ password=self.user['password'])
+ r = self.post('/auth/tokens?nocatalog', body=auth_data)
+ self.assertValidProjectScopedTokenResponse(r, require_catalog=False)
+ self.assertEqual(r.result['token']['project']['id'], project['id'])
+
+ def test_implicit_project_id_scoped_token_with_user_id_no_catalog(self):
+ # attempt to authenticate without requesting a project
+ auth_data = self.build_authentication_request(
+ user_id=self.user['id'],
+ password=self.user['password'],
+ project_id=self.project['id'])
+ r = self.post('/auth/tokens?nocatalog', body=auth_data)
+ self.assertValidProjectScopedTokenResponse(r, require_catalog=False)
+ self.assertEqual(r.result['token']['project']['id'],
+ self.project['id'])
+
def test_default_project_id_scoped_token_with_user_id_401(self):
# create a second project to work with
ref = self.new_project_ref(domain_id=self.domain['id'])
@@ -888,6 +938,137 @@ class TestAuthJSON(test_v3.RestfulTestCase):
project_id=project['id'])
self.post('/auth/tokens', body=auth_data, expected_status=401)
+ def test_user_and_group_roles_scoped_token(self):
+ """Test correct roles are returned in scoped token.
+
+ Test Plan:
+ - Create a domain, with 1 project, 2 users (user1 and user2)
+ and 2 groups (group1 and group2)
+ - Make user1 a member of group1, user2 a member of group2
+ - Create 8 roles, assigning them to each of the 8 combinations
+ of users/groups on domain/project
+ - Get a project scoped token for user1, checking that the right
+ two roles are returned (one directly assigned, one by virtue
+ of group membership)
+ - Repeat this for a domain scoped token
+ - Make user1 also a member of group2
+ - Get another scoped token making sure the additional role
+ shows up
+ - User2 is just here as a spoiler, to make sure we don't get
+ any roles uniquely assigned to it returned in any of our
+ tokens
+
+ """
+
+ domainA = self.new_domain_ref()
+ self.identity_api.create_domain(domainA['id'], domainA)
+ projectA = self.new_project_ref(domain_id=domainA['id'])
+ self.identity_api.create_project(projectA['id'], projectA)
+
+ user1 = self.new_user_ref(
+ domain_id=domainA['id'])
+ user1['password'] = uuid.uuid4().hex
+ self.identity_api.create_user(user1['id'], user1)
+
+ user2 = self.new_user_ref(
+ domain_id=domainA['id'])
+ user2['password'] = uuid.uuid4().hex
+ self.identity_api.create_user(user2['id'], user2)
+
+ group1 = self.new_group_ref(
+ domain_id=domainA['id'])
+ self.identity_api.create_group(group1['id'], group1)
+
+ group2 = self.new_group_ref(
+ domain_id=domainA['id'])
+ self.identity_api.create_group(group2['id'], group2)
+
+ self.identity_api.add_user_to_group(user1['id'],
+ group1['id'])
+ self.identity_api.add_user_to_group(user2['id'],
+ group2['id'])
+
+ # Now create all the roles and assign them
+ role_list = []
+ for _ in range(8):
+ role = self.new_role_ref()
+ self.identity_api.create_role(role['id'], role)
+ role_list.append(role)
+
+ self.identity_api.create_grant(role_list[0]['id'],
+ user_id=user1['id'],
+ domain_id=domainA['id'])
+ self.identity_api.create_grant(role_list[1]['id'],
+ user_id=user1['id'],
+ project_id=projectA['id'])
+ self.identity_api.create_grant(role_list[2]['id'],
+ user_id=user2['id'],
+ domain_id=domainA['id'])
+ self.identity_api.create_grant(role_list[3]['id'],
+ user_id=user2['id'],
+ project_id=projectA['id'])
+ self.identity_api.create_grant(role_list[4]['id'],
+ group_id=group1['id'],
+ domain_id=domainA['id'])
+ self.identity_api.create_grant(role_list[5]['id'],
+ group_id=group1['id'],
+ project_id=projectA['id'])
+ self.identity_api.create_grant(role_list[6]['id'],
+ group_id=group2['id'],
+ domain_id=domainA['id'])
+ self.identity_api.create_grant(role_list[7]['id'],
+ group_id=group2['id'],
+ project_id=projectA['id'])
+
+ # First, get a project scoped token - which should
+ # contain the direct user role and the one by virtue
+ # of group membership
+ auth_data = self.build_authentication_request(
+ user_id=user1['id'],
+ password=user1['password'],
+ project_id=projectA['id'])
+ r = self.post('/auth/tokens', body=auth_data)
+ token = self.assertValidScopedTokenResponse(r)
+ roles_ids = []
+ for i, ref in enumerate(token['roles']):
+ roles_ids.append(ref['id'])
+ self.assertEqual(len(token['roles']), 2)
+ self.assertIn(role_list[1]['id'], roles_ids)
+ self.assertIn(role_list[5]['id'], roles_ids)
+
+ # Now the same thing for a domain scoped token
+ auth_data = self.build_authentication_request(
+ user_id=user1['id'],
+ password=user1['password'],
+ domain_id=domainA['id'])
+ r = self.post('/auth/tokens', body=auth_data)
+ token = self.assertValidScopedTokenResponse(r)
+ roles_ids = []
+ for i, ref in enumerate(token['roles']):
+ roles_ids.append(ref['id'])
+ self.assertEqual(len(token['roles']), 2)
+ self.assertIn(role_list[0]['id'], roles_ids)
+ self.assertIn(role_list[4]['id'], roles_ids)
+
+ # Finally, add user1 to the 2nd group, and get a new
+ # scoped token - the extra role should now be included
+ # by virtue of the 2nd group
+ self.identity_api.add_user_to_group(user1['id'],
+ group2['id'])
+ auth_data = self.build_authentication_request(
+ user_id=user1['id'],
+ password=user1['password'],
+ project_id=projectA['id'])
+ r = self.post('/auth/tokens', body=auth_data)
+ token = self.assertValidScopedTokenResponse(r)
+ roles_ids = []
+ for i, ref in enumerate(token['roles']):
+ roles_ids.append(ref['id'])
+ self.assertEqual(len(token['roles']), 3)
+ self.assertIn(role_list[1]['id'], roles_ids)
+ self.assertIn(role_list[5]['id'], roles_ids)
+ self.assertIn(role_list[7]['id'], roles_ids)
+
def test_project_id_scoped_token_with_user_domain_id(self):
auth_data = self.build_authentication_request(
username=self.user['name'],
@@ -1072,31 +1253,155 @@ class TestAuthJSON(test_v3.RestfulTestCase):
password=uuid.uuid4().hex)
self.post('/auth/tokens', body=auth_data, expected_status=401)
- def test_remote_user(self):
+ def test_remote_user_no_realm(self):
+ CONF.auth.methods = 'external'
+ api = auth.controllers.Auth()
+ auth_data = self.build_authentication_request()['auth']
+ context = {'REMOTE_USER': self.default_domain_user['name']}
+ auth_info = auth.controllers.AuthInfo(None, auth_data)
+ auth_context = {'extras': {}, 'method_names': []}
+ api.authenticate(context, auth_info, auth_context)
+ self.assertEqual(auth_context['user_id'],
+ self.default_domain_user['id'])
+
+ def test_remote_user_no_domain(self):
+ auth_data = self.build_authentication_request()['auth']
+ api = auth.controllers.Auth()
+ context = {'REMOTE_USER': self.user['name']}
+ auth_info = auth.controllers.AuthInfo(None, auth_data)
+ auth_context = {'extras': {}, 'method_names': []}
+ self.assertRaises(exception.Unauthorized,
+ api.authenticate,
+ context,
+ auth_info,
+ auth_context)
+
+ def test_remote_user_and_password(self):
+ #both REMOTE_USER and password methods must pass.
+ #note that they do not have to match
auth_data = self.build_authentication_request(
- user_id=self.user['id'],
+ user_domain_id=self.domain['id'],
+ username=self.user['name'],
password=self.user['password'])['auth']
api = auth.controllers.Auth()
- context = {'REMOTE_USER': self.user['name']}
+ context = {'REMOTE_USER': self.default_domain_user['name']}
auth_info = auth.controllers.AuthInfo(None, auth_data)
auth_context = {'extras': {}, 'method_names': []}
api.authenticate(context, auth_info, auth_context)
- self.assertEqual(auth_context['user_id'], self.user['id'])
- def test_remote_user_no_domain(self):
+ def test_remote_user_and_explicit_external(self):
+ #both REMOTE_USER and password methods must pass.
+ #note that they do not have to match
auth_data = self.build_authentication_request(
+ user_domain_id=self.domain['id'],
username=self.user['name'],
password=self.user['password'])['auth']
+ auth_data['identity']['methods'] = ["password", "external"]
+ auth_data['identity']['external'] = {}
api = auth.controllers.Auth()
- context = {'REMOTE_USER': self.user['name']}
+ context = {}
auth_info = auth.controllers.AuthInfo(None, auth_data)
auth_context = {'extras': {}, 'method_names': []}
- self.assertRaises(exception.ValidationError,
+ self.assertRaises(exception.Unauthorized,
api.authenticate,
context,
auth_info,
auth_context)
+ def test_remote_user_bad_password(self):
+ #both REMOTE_USER and password methods must pass.
+ auth_data = self.build_authentication_request(
+ user_domain_id=self.domain['id'],
+ username=self.user['name'],
+ password='badpassword')['auth']
+ api = auth.controllers.Auth()
+ context = {'REMOTE_USER': self.default_domain_user['name']}
+ auth_info = auth.controllers.AuthInfo(None, auth_data)
+ auth_context = {'extras': {}, 'method_names': []}
+ self.assertRaises(exception.Unauthorized,
+ api.authenticate,
+ context,
+ auth_info,
+ auth_context)
+
+ def test_bind_not_set_with_remote_user(self):
+ CONF.token.bind = []
+ auth_data = self.build_authentication_request()
+ remote_user = self.default_domain_user['name']
+ self.admin_app.extra_environ.update({'REMOTE_USER': remote_user,
+ 'AUTH_TYPE': 'Negotiate'})
+ r = self.post('/auth/tokens', body=auth_data)
+ token = self.assertValidUnscopedTokenResponse(r)
+ self.assertNotIn('bind', token)
+
+ #TODO(ayoung): move to TestPKITokenAPIs; it will be run for both formats
+ def test_verify_with_bound_token(self):
+ self.opt_in_group('token', bind='kerberos')
+ auth_data = self.build_authentication_request(
+ project_id=self.project['id'])
+ remote_user = self.default_domain_user['name']
+ self.admin_app.extra_environ.update({'REMOTE_USER': remote_user,
+ 'AUTH_TYPE': 'Negotiate'})
+
+ resp = self.post('/auth/tokens', body=auth_data)
+
+ token = resp.headers.get('X-Subject-Token')
+ headers = {'X-Subject-Token': token}
+ r = self.get('/auth/tokens', headers=headers, token=token)
+ token = self.assertValidProjectScopedTokenResponse(r)
+ self.assertEqual(token['bind']['kerberos'],
+ self.default_domain_user['name'])
+
+ def test_auth_with_bind_token(self):
+ CONF.token.bind = ['kerberos']
+
+ auth_data = self.build_authentication_request()
+ remote_user = self.default_domain_user['name']
+ self.admin_app.extra_environ.update({'REMOTE_USER': remote_user,
+ 'AUTH_TYPE': 'Negotiate'})
+ r = self.post('/auth/tokens', body=auth_data)
+
+ # the unscoped token should have bind information in it
+ token = self.assertValidUnscopedTokenResponse(r)
+ self.assertEqual(token['bind']['kerberos'], remote_user)
+
+ token = r.headers.get('X-Subject-Token')
+
+ # using unscoped token with remote user succeeds
+ auth_params = {'token': token, 'project_id': self.project_id}
+ auth_data = self.build_authentication_request(**auth_params)
+ r = self.post('/auth/tokens', body=auth_data)
+ token = self.assertValidProjectScopedTokenResponse(r)
+
+ # the bind information should be carried over from the original token
+ self.assertEqual(token['bind']['kerberos'], remote_user)
+
+ def test_v2_v3_bind_token_intermix(self):
+ self.opt_in_group('token', bind='kerberos')
+
+ # we need our own user registered to the default domain because of
+ # the way external auth works.
+ remote_user = self.default_domain_user['name']
+ self.admin_app.extra_environ.update({'REMOTE_USER': remote_user,
+ 'AUTH_TYPE': 'Negotiate'})
+ body = {'auth': {}}
+ resp = self.admin_request(path='/v2.0/tokens',
+ method='POST',
+ body=body)
+
+ v2_token_data = resp.result
+
+ bind = v2_token_data['access']['token']['bind']
+ self.assertEqual(bind['kerberos'], self.default_domain_user['name'])
+
+ v2_token_id = v2_token_data['access']['token']['id']
+ headers = {'X-Subject-Token': v2_token_id}
+ resp = self.get('/auth/tokens', headers=headers)
+ token_data = resp.result
+
+ self.assertDictEqual(v2_token_data['access']['token']['bind'],
+ token_data['token']['bind'])
+
class TestAuthXML(TestAuthJSON):
content_type = 'xml'
@@ -1131,7 +1436,7 @@ class TestTrustAuth(TestAuthInfo):
self.identity_api.create_user(self.trustee_user_id, self.trustee_user)
def test_create_trust_400(self):
- raise nose.exc.SkipTest('Blocked by bug 1133435')
+ self.skipTest('Blocked by bug 1133435')
self.post('/OS-TRUST/trusts', body={'trust': {}}, expected_status=400)
def test_create_unscoped_trust(self):
diff --git a/tests/test_v3_identity.py b/tests/test_v3_identity.py
index 1e10070e..f1e19c42 100644
--- a/tests/test_v3_identity.py
+++ b/tests/test_v3_identity.py
@@ -16,11 +16,64 @@
import uuid
+from keystone import config
from keystone import exception
import test_v3
+def _build_role_assignment_url_and_entity(
+ role_id, user_id=None, group_id=None, domain_id=None,
+ project_id=None, inherited_to_projects=False,
+ effective=False):
+
+ if user_id and domain_id:
+ url = ('/domains/%(domain_id)s/users/%(user_id)s'
+ '/roles/%(role_id)s' % {
+ 'domain_id': domain_id,
+ 'user_id': user_id,
+ 'role_id': role_id})
+ entity = {'role': {'id': role_id},
+ 'user': {'id': user_id},
+ 'scope': {'domain': {'id': domain_id}}}
+ if inherited_to_projects:
+ url = '/OS-INHERIT%s/inherited_to_projects' % url
+ if not effective:
+ entity['OS-INHERIT:inherited_to'] = 'projects'
+ elif user_id and project_id:
+ url = ('/projects/%(project_id)s/users/%(user_id)s'
+ '/roles/%(role_id)s' % {
+ 'project_id': project_id,
+ 'user_id': user_id,
+ 'role_id': role_id})
+ entity = {'role': {'id': role_id},
+ 'user': {'id': user_id},
+ 'scope': {'project': {'id': project_id}}}
+ if group_id and domain_id:
+ url = ('/domains/%(domain_id)s/groups/%(group_id)s'
+ '/roles/%(role_id)s' % {
+ 'domain_id': domain_id,
+ 'group_id': group_id,
+ 'role_id': role_id})
+ entity = {'role': {'id': role_id},
+ 'group': {'id': group_id},
+ 'scope': {'domain': {'id': domain_id}}}
+ if inherited_to_projects:
+ url = '/OS-INHERIT%s/inherited_to_projects' % url
+ if not effective:
+ entity['OS-INHERIT:inherited_to'] = 'projects'
+ elif group_id and project_id:
+ url = ('/projects/%(project_id)s/groups/%(group_id)s'
+ '/roles/%(role_id)s' % {
+ 'project_id': project_id,
+ 'group_id': group_id,
+ 'role_id': role_id})
+ entity = {'role': {'id': role_id},
+ 'group': {'id': group_id},
+ 'scope': {'project': {'id': project_id}}}
+ return (url, entity)
+
+
class IdentityTestCase(test_v3.RestfulTestCase):
"""Test domains, projects, users, groups, & role CRUD."""
@@ -52,6 +105,10 @@ class IdentityTestCase(test_v3.RestfulTestCase):
body={'domain': ref})
return self.assertValidDomainResponse(r, ref)
+ def test_create_domain_400(self):
+ """Call ``POST /domains``."""
+ self.post('/domains', body={'domain': {}}, expected_status=400)
+
def test_list_domains(self):
"""Call ``GET /domains``."""
r = self.get('/domains')
@@ -213,19 +270,19 @@ class IdentityTestCase(test_v3.RestfulTestCase):
# Check all the domain2 relevant entities are gone
self.assertRaises(exception.DomainNotFound,
self.identity_api.get_domain,
- domain_id=self.domain2['id'])
+ self.domain2['id'])
self.assertRaises(exception.ProjectNotFound,
self.identity_api.get_project,
- tenant_id=self.project2['id'])
+ self.project2['id'])
self.assertRaises(exception.GroupNotFound,
self.identity_api.get_group,
- group_id=self.group2['id'])
+ self.group2['id'])
self.assertRaises(exception.UserNotFound,
self.identity_api.get_user,
- user_id=self.user2['id'])
+ self.user2['id'])
self.assertRaises(exception.CredentialNotFound,
self.credential_api.get_credential,
- credential_id=self.credential2['id'])
+ self.credential2['id'])
# ...and that all self.domain entities are still here
r = self.identity_api.get_domain(self.domain['id'])
@@ -260,6 +317,10 @@ class IdentityTestCase(test_v3.RestfulTestCase):
body={'project': ref})
self.assertValidProjectResponse(r, ref)
+ def test_create_project_400(self):
+ """Call ``POST /projects``."""
+ self.post('/projects', body={'project': {}}, expected_status=400)
+
def test_get_project(self):
"""Call ``GET /projects/{project_id}``."""
r = self.get(
@@ -323,6 +384,10 @@ class IdentityTestCase(test_v3.RestfulTestCase):
body={'user': ref})
return self.assertValidUserResponse(r, ref)
+ def test_create_user_400(self):
+ """Call ``POST /users``."""
+ self.post('/users', body={'user': {}}, expected_status=400)
+
def test_list_users(self):
"""Call ``GET /users``."""
r = self.get('/users')
@@ -458,7 +523,7 @@ class IdentityTestCase(test_v3.RestfulTestCase):
# that reference this project
self.assertRaises(exception.CredentialNotFound,
self.credential_api.get_credential,
- credential_id=self.credential['id'])
+ self.credential['id'])
# And the no tokens we remain valid
tokens = self.token_api.list_tokens(self.user['id'])
self.assertEquals(len(tokens), 0)
@@ -476,6 +541,10 @@ class IdentityTestCase(test_v3.RestfulTestCase):
body={'group': ref})
return self.assertValidGroupResponse(r, ref)
+ def test_create_group_400(self):
+ """Call ``POST /groups``."""
+ self.post('/groups', body={'group': {}}, expected_status=400)
+
def test_list_groups(self):
"""Call ``GET /groups``."""
r = self.get('/groups')
@@ -516,6 +585,10 @@ class IdentityTestCase(test_v3.RestfulTestCase):
body={'role': ref})
return self.assertValidRoleResponse(r, ref)
+ def test_create_role_400(self):
+ """Call ``POST /roles``."""
+ self.post('/roles', body={'role': {}}, expected_status=400)
+
def test_list_roles(self):
"""Call ``GET /roles``."""
r = self.get('/roles')
@@ -627,3 +700,858 @@ class IdentityTestCase(test_v3.RestfulTestCase):
r = self.get(collection_url)
self.assertValidRoleListResponse(r, expected_length=0)
self.assertIn(collection_url, r.result['links']['self'])
+
+ def test_get_role_assignments(self):
+ """Call ``GET /role_assignments``.
+
+ The sample data set up already has a user, group and project
+ that is part of self.domain. We use these plus a new user
+ we create as our data set, making sure we ignore any
+ role assignments that are already in existence.
+
+ Since we don't yet support a first class entity for role
+ assignments, we are only testing the LIST API. To create
+ and delete the role assignments we use the old grant APIs.
+
+ Test Plan:
+ - Create extra user for tests
+ - Get a list of all existing role assignments
+ - Add a new assignment for each of the four combinations, i.e.
+ group+domain, user+domain, group+project, user+project, using
+ the same role each time
+ - Get a new list of all role assignments, checking these four new
+ ones have been added
+ - Then delete the four we added
+ - Get a new list of all role assignments, checking the four have
+ been removed
+
+ """
+
+ # Since the default fixtures already assign some roles to the
+ # user it creates, we also need a new user that will not have any
+ # existing assignments
+ self.user1 = self.new_user_ref(
+ domain_id=self.domain['id'])
+ self.user1['password'] = uuid.uuid4().hex
+ self.identity_api.create_user(self.user1['id'], self.user1)
+
+ collection_url = '/role_assignments'
+ r = self.get(collection_url)
+ self.assertValidRoleAssignmentListResponse(r)
+ self.assertIn(collection_url, r.result['links']['self'])
+ existing_assignments = len(r.result.get('role_assignments'))
+
+ # Now add one of each of the four types of assignment, making sure
+ # that we get them all back.
+ gd_url, gd_entity = _build_role_assignment_url_and_entity(
+ domain_id=self.domain_id, group_id=self.group_id,
+ role_id=self.role_id)
+ self.put(gd_url)
+ r = self.get(collection_url)
+ self.assertValidRoleAssignmentListResponse(r)
+ self.assertEqual(len(r.result.get('role_assignments')),
+ existing_assignments + 1)
+ self.assertRoleAssignmentInListResponse(r, gd_entity, link_url=gd_url)
+
+ ud_url, ud_entity = _build_role_assignment_url_and_entity(
+ domain_id=self.domain_id, user_id=self.user1['id'],
+ role_id=self.role_id)
+ self.put(ud_url)
+ r = self.get(collection_url)
+ self.assertValidRoleAssignmentListResponse(r)
+ self.assertEqual(len(r.result.get('role_assignments')),
+ existing_assignments + 2)
+ self.assertRoleAssignmentInListResponse(r, ud_entity, link_url=ud_url)
+
+ gp_url, gp_entity = _build_role_assignment_url_and_entity(
+ project_id=self.project_id, group_id=self.group_id,
+ role_id=self.role_id)
+ self.put(gp_url)
+ r = self.get(collection_url)
+ self.assertValidRoleAssignmentListResponse(r)
+ self.assertEqual(len(r.result.get('role_assignments')),
+ existing_assignments + 3)
+ self.assertRoleAssignmentInListResponse(r, gp_entity, link_url=gp_url)
+
+ up_url, up_entity = _build_role_assignment_url_and_entity(
+ project_id=self.project_id, user_id=self.user1['id'],
+ role_id=self.role_id)
+ self.put(up_url)
+ r = self.get(collection_url)
+ self.assertValidRoleAssignmentListResponse(r)
+ self.assertEqual(len(r.result.get('role_assignments')),
+ existing_assignments + 4)
+ self.assertRoleAssignmentInListResponse(r, up_entity, link_url=up_url)
+
+ # Now delete the four we added and make sure they are removed
+ # from the collection.
+
+ self.delete(gd_url)
+ self.delete(ud_url)
+ self.delete(gp_url)
+ self.delete(up_url)
+ r = self.get(collection_url)
+ self.assertValidRoleAssignmentListResponse(r)
+ self.assertEqual(len(r.result.get('role_assignments')),
+ existing_assignments)
+ self.assertRoleAssignmentNotInListResponse(r, gd_entity)
+ self.assertRoleAssignmentNotInListResponse(r, ud_entity)
+ self.assertRoleAssignmentNotInListResponse(r, gp_entity)
+ self.assertRoleAssignmentNotInListResponse(r, up_entity)
+
+ def test_get_effective_role_assignments(self):
+ """Call ``GET /role_assignments?effective``.
+
+ Test Plan:
+ - Create two extra user for tests
+ - Add these users to a group
+ - Add a role assignment for the group on a domain
+ - Get a list of all role assignments, checking one has been added
+ - Then get a list of all effective role assignments - the group
+ assignment should have turned into assignments on the domain
+ for each of the group members.
+
+ """
+ self.user1 = self.new_user_ref(
+ domain_id=self.domain['id'])
+ self.user1['password'] = uuid.uuid4().hex
+ self.identity_api.create_user(self.user1['id'], self.user1)
+ self.user2 = self.new_user_ref(
+ domain_id=self.domain['id'])
+ self.user2['password'] = uuid.uuid4().hex
+ self.identity_api.create_user(self.user2['id'], self.user2)
+ self.identity_api.add_user_to_group(self.user1['id'], self.group['id'])
+ self.identity_api.add_user_to_group(self.user2['id'], self.group['id'])
+
+ collection_url = '/role_assignments'
+ r = self.get(collection_url)
+ self.assertValidRoleAssignmentListResponse(r)
+ self.assertIn(collection_url, r.result['links']['self'])
+ existing_assignments = len(r.result.get('role_assignments'))
+
+ gd_url, gd_entity = _build_role_assignment_url_and_entity(
+ domain_id=self.domain_id, group_id=self.group_id,
+ role_id=self.role_id)
+ self.put(gd_url)
+ r = self.get(collection_url)
+ self.assertValidRoleAssignmentListResponse(r)
+ self.assertEqual(len(r.result.get('role_assignments')),
+ existing_assignments + 1)
+ self.assertRoleAssignmentInListResponse(r, gd_entity, link_url=gd_url)
+
+ # Now re-read the collection asking for effective roles - this
+ # should mean the group assignment is translated into the two
+ # member user assignments
+ collection_url = '/role_assignments?effective'
+ r = self.get(collection_url)
+ self.assertValidRoleAssignmentListResponse(r)
+ self.assertEqual(len(r.result.get('role_assignments')),
+ existing_assignments + 2)
+ unused, ud_entity = _build_role_assignment_url_and_entity(
+ domain_id=self.domain_id, user_id=self.user1['id'],
+ role_id=self.role_id)
+ gd_url, unused = _build_role_assignment_url_and_entity(
+ domain_id=self.domain_id, group_id=self.group['id'],
+ role_id=self.role_id)
+ self.assertRoleAssignmentInListResponse(r, ud_entity, link_url=gd_url)
+ ud_url, ud_entity = _build_role_assignment_url_and_entity(
+ domain_id=self.domain_id, user_id=self.user2['id'],
+ role_id=self.role_id)
+ self.assertRoleAssignmentInListResponse(r, ud_entity, link_url=gd_url)
+
+ def test_check_effective_values_for_role_assignments(self):
+ """Call ``GET /role_assignments?effective=value``.
+
+ Check the various ways of specifying the 'effective'
+ query parameter. If the 'effective' query parameter
+ is included then this should always be treated as
+ as meaning 'True' unless it is specified as:
+
+ {url}?effective=0
+
+ This is by design to match the agreed way of handling
+ policy checking on query/filter parameters.
+
+ Test Plan:
+ - Create two extra user for tests
+ - Add these users to a group
+ - Add a role assignment for the group on a domain
+ - Get a list of all role assignments, checking one has been added
+ - Then issue various request with different ways of defining
+ the 'effective' query parameter. As we have tested the
+ correctness of the data coming back when we get effective roles
+ in other tests, here we just use the count of entities to
+ know if we are getting effective roles or not
+
+ """
+ self.user1 = self.new_user_ref(
+ domain_id=self.domain['id'])
+ self.user1['password'] = uuid.uuid4().hex
+ self.identity_api.create_user(self.user1['id'], self.user1)
+ self.user2 = self.new_user_ref(
+ domain_id=self.domain['id'])
+ self.user2['password'] = uuid.uuid4().hex
+ self.identity_api.create_user(self.user2['id'], self.user2)
+ self.identity_api.add_user_to_group(self.user1['id'], self.group['id'])
+ self.identity_api.add_user_to_group(self.user2['id'], self.group['id'])
+
+ collection_url = '/role_assignments'
+ r = self.get(collection_url)
+ self.assertValidRoleAssignmentListResponse(r)
+ existing_assignments = len(r.result.get('role_assignments'))
+
+ gd_url, gd_entity = _build_role_assignment_url_and_entity(
+ domain_id=self.domain_id, group_id=self.group_id,
+ role_id=self.role_id)
+ self.put(gd_url)
+ r = self.get(collection_url)
+ self.assertValidRoleAssignmentListResponse(r)
+ self.assertEqual(len(r.result.get('role_assignments')),
+ existing_assignments + 1)
+ self.assertRoleAssignmentInListResponse(r, gd_entity, link_url=gd_url)
+
+ # Now re-read the collection asking for effective roles,
+ # using the most common way of defining "effective'. This
+ # should mean the group assignment is translated into the two
+ # member user assignments
+ collection_url = '/role_assignments?effective'
+ r = self.get(collection_url)
+ self.assertValidRoleAssignmentListResponse(r)
+ self.assertEqual(len(r.result.get('role_assignments')),
+ existing_assignments + 2)
+ # Now set 'effective' to false explicitly - should get
+ # back the regular roles
+ collection_url = '/role_assignments?effective=0'
+ r = self.get(collection_url)
+ self.assertValidRoleAssignmentListResponse(r)
+ self.assertEqual(len(r.result.get('role_assignments')),
+ existing_assignments + 1)
+ # Now try setting 'effective' to 'False' explicitly- this is
+ # NOT supported as a way of setting a query or filter
+ # parameter to false by design. Hence we should get back
+ # effective roles.
+ collection_url = '/role_assignments?effective=False'
+ r = self.get(collection_url)
+ self.assertValidRoleAssignmentListResponse(r)
+ self.assertEqual(len(r.result.get('role_assignments')),
+ existing_assignments + 2)
+ # Now set 'effective' to True explicitly
+ collection_url = '/role_assignments?effective=True'
+ r = self.get(collection_url)
+ self.assertValidRoleAssignmentListResponse(r)
+ self.assertEqual(len(r.result.get('role_assignments')),
+ existing_assignments + 2)
+
+ def test_filtered_role_assignments(self):
+ """Call ``GET /role_assignments?filters``.
+
+ Test Plan:
+ - Create extra users, group, role and project for tests
+ - Make the following assignments:
+ Give group1, role1 on project1 and domain
+ Give user1, role2 on project1 and domain
+ Make User1 a member of Group1
+ - Test a series of single filter list calls, checking that
+ the correct results are obtained
+ - Test a multi-filtered list call
+ - Test listing all effective roles for a given user
+ - Test the equivalent of the list of roles in a project scoped
+ token (all effective roles for a user on a project)
+
+ """
+
+ # Since the default fixtures already assign some roles to the
+ # user it creates, we also need a new user that will not have any
+ # existing assignments
+ self.user1 = self.new_user_ref(
+ domain_id=self.domain['id'])
+ self.user1['password'] = uuid.uuid4().hex
+ self.identity_api.create_user(self.user1['id'], self.user1)
+ self.user2 = self.new_user_ref(
+ domain_id=self.domain['id'])
+ self.user2['password'] = uuid.uuid4().hex
+ self.identity_api.create_user(self.user2['id'], self.user2)
+ self.group1 = self.new_group_ref(
+ domain_id=self.domain['id'])
+ self.identity_api.create_group(self.group1['id'], self.group1)
+ self.identity_api.add_user_to_group(self.user1['id'],
+ self.group1['id'])
+ self.identity_api.add_user_to_group(self.user2['id'],
+ self.group1['id'])
+ self.project1 = self.new_project_ref(
+ domain_id=self.domain['id'])
+ self.identity_api.create_project(self.project1['id'], self.project1)
+ self.role1 = self.new_role_ref()
+ self.identity_api.create_role(self.role1['id'], self.role1)
+ self.role2 = self.new_role_ref()
+ self.identity_api.create_role(self.role2['id'], self.role2)
+
+ # Now add one of each of the four types of assignment
+
+ gd_url, gd_entity = _build_role_assignment_url_and_entity(
+ domain_id=self.domain_id, group_id=self.group1['id'],
+ role_id=self.role1['id'])
+ self.put(gd_url)
+
+ ud_url, ud_entity = _build_role_assignment_url_and_entity(
+ domain_id=self.domain_id, user_id=self.user1['id'],
+ role_id=self.role2['id'])
+ self.put(ud_url)
+
+ gp_url, gp_entity = _build_role_assignment_url_and_entity(
+ project_id=self.project1['id'], group_id=self.group1['id'],
+ role_id=self.role1['id'])
+ self.put(gp_url)
+
+ up_url, up_entity = _build_role_assignment_url_and_entity(
+ project_id=self.project1['id'], user_id=self.user1['id'],
+ role_id=self.role2['id'])
+ self.put(up_url)
+
+ # Now list by various filters to make sure we get back the right ones
+
+ collection_url = ('/role_assignments?scope.project.id=%s' %
+ self.project1['id'])
+ r = self.get(collection_url)
+ self.assertValidRoleAssignmentListResponse(r)
+ self.assertEqual(len(r.result.get('role_assignments')), 2)
+ self.assertRoleAssignmentInListResponse(r, up_entity, link_url=up_url)
+ self.assertRoleAssignmentInListResponse(r, gp_entity, link_url=gp_url)
+
+ collection_url = ('/role_assignments?scope.domain.id=%s' %
+ self.domain['id'])
+ r = self.get(collection_url)
+ self.assertValidRoleAssignmentListResponse(r)
+ self.assertEqual(len(r.result.get('role_assignments')), 2)
+ self.assertRoleAssignmentInListResponse(r, ud_entity, link_url=ud_url)
+ self.assertRoleAssignmentInListResponse(r, gd_entity, link_url=gd_url)
+
+ collection_url = '/role_assignments?user.id=%s' % self.user1['id']
+ r = self.get(collection_url)
+ self.assertValidRoleAssignmentListResponse(r)
+ self.assertEqual(len(r.result.get('role_assignments')), 2)
+ self.assertRoleAssignmentInListResponse(r, up_entity, link_url=up_url)
+ self.assertRoleAssignmentInListResponse(r, ud_entity, link_url=ud_url)
+
+ collection_url = '/role_assignments?group.id=%s' % self.group1['id']
+ r = self.get(collection_url)
+ self.assertValidRoleAssignmentListResponse(r)
+ self.assertEqual(len(r.result.get('role_assignments')), 2)
+ self.assertRoleAssignmentInListResponse(r, gd_entity, link_url=gd_url)
+ self.assertRoleAssignmentInListResponse(r, gp_entity, link_url=gp_url)
+
+ collection_url = '/role_assignments?role.id=%s' % self.role1['id']
+ r = self.get(collection_url)
+ self.assertValidRoleAssignmentListResponse(r)
+ self.assertEqual(len(r.result.get('role_assignments')), 2)
+ self.assertRoleAssignmentInListResponse(r, gd_entity, link_url=gd_url)
+ self.assertRoleAssignmentInListResponse(r, gp_entity, link_url=gp_url)
+
+ # Let's try combining two filers together....
+
+ collection_url = (
+ '/role_assignments?user.id=%(user_id)s'
+ '&scope.project.id=%(project_id)s' % {
+ 'user_id': self.user1['id'],
+ 'project_id': self.project1['id']})
+ r = self.get(collection_url)
+ self.assertValidRoleAssignmentListResponse(r)
+ self.assertEqual(len(r.result.get('role_assignments')), 1)
+ self.assertRoleAssignmentInListResponse(r, up_entity, link_url=up_url)
+
+ # Now for a harder one - filter for user with effective
+ # roles - this should return role assignment that were directly
+ # assigned as well as by virtue of group membership
+
+ collection_url = ('/role_assignments?effective&user.id=%s' %
+ self.user1['id'])
+ r = self.get(collection_url)
+ self.assertValidRoleAssignmentListResponse(r)
+ self.assertEqual(len(r.result.get('role_assignments')), 4)
+ # Should have the two direct roles...
+ self.assertRoleAssignmentInListResponse(r, up_entity, link_url=up_url)
+ self.assertRoleAssignmentInListResponse(r, ud_entity, link_url=ud_url)
+ # ...and the two via group membership...
+ unused, up1_entity = _build_role_assignment_url_and_entity(
+ project_id=self.project1['id'], user_id=self.user1['id'],
+ role_id=self.role1['id'])
+ unused, ud1_entity = _build_role_assignment_url_and_entity(
+ domain_id=self.domain_id, user_id=self.user1['id'],
+ role_id=self.role1['id'])
+ gp1_url, unused = _build_role_assignment_url_and_entity(
+ project_id=self.project1['id'], group_id=self.group1['id'],
+ role_id=self.role1['id'])
+ gd1_url, unused = _build_role_assignment_url_and_entity(
+ domain_id=self.domain_id, group_id=self.group1['id'],
+ role_id=self.role1['id'])
+ self.assertRoleAssignmentInListResponse(r, up1_entity,
+ link_url=gp1_url)
+ self.assertRoleAssignmentInListResponse(r, ud1_entity,
+ link_url=gd1_url)
+
+ # ...and for the grand-daddy of them all, simulate the request
+ # that would generate the list of effective roles in a project
+ # scoped token.
+
+ collection_url = (
+ '/role_assignments?effective&user.id=%(user_id)s'
+ '&scope.project.id=%(project_id)s' % {
+ 'user_id': self.user1['id'],
+ 'project_id': self.project1['id']})
+ r = self.get(collection_url)
+ self.assertValidRoleAssignmentListResponse(r)
+ self.assertEqual(len(r.result.get('role_assignments')), 2)
+ # Should have one direct role and one from group membership...
+ self.assertRoleAssignmentInListResponse(r, up_entity, link_url=up_url)
+ self.assertRoleAssignmentInListResponse(r, up1_entity,
+ link_url=gp1_url)
+
+
+class IdentityIneritanceTestCase(test_v3.RestfulTestCase):
+ """Test inheritance crud and its effects."""
+
+ def setUp(self):
+ self.orig_extension_enablement = config.CONF.os_inherit.enabled
+ self.opt_in_group('os_inherit', enabled=True)
+ super(IdentityIneritanceTestCase, self).setUp()
+
+ def tearDown(self):
+ super(IdentityIneritanceTestCase, self).tearDown()
+ self.opt_in_group('os_inherit', enabled=self.orig_extension_enablement)
+
+ def test_crud_user_inherited_domain_role_grants(self):
+ role_list = []
+ for _ in range(2):
+ role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex}
+ self.assignment_api.create_role(role['id'], role)
+ role_list.append(role)
+
+ # Create a non-inherited role as a spoiler
+ self.assignment_api.create_grant(
+ role_list[1]['id'], user_id=self.user['id'],
+ domain_id=self.domain_id)
+
+ base_collection_url = (
+ '/OS-INHERIT/domains/%(domain_id)s/users/%(user_id)s/roles' % {
+ 'domain_id': self.domain_id,
+ 'user_id': self.user['id']})
+ member_url = '%(collection_url)s/%(role_id)s/inherited_to_projects' % {
+ 'collection_url': base_collection_url,
+ 'role_id': role_list[0]['id']}
+ collection_url = base_collection_url + '/inherited_to_projects'
+
+ self.put(member_url)
+
+ # Check we can read it back
+ self.head(member_url)
+ r = self.get(collection_url)
+ self.assertValidRoleListResponse(r, ref=role_list[0])
+ self.assertIn(collection_url, r.result['links']['self'])
+
+ # Now delete and check its gone
+ self.delete(member_url)
+ r = self.get(collection_url)
+ self.assertValidRoleListResponse(r, expected_length=0)
+ self.assertIn(collection_url, r.result['links']['self'])
+
+ def test_crud_inherited_role_grants_failed_if_disabled(self):
+ # Disable the extension and check no API calls can be issued
+ self.opt_in_group('os_inherit', enabled=False)
+ super(IdentityIneritanceTestCase, self).setUp()
+
+ role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex}
+ self.assignment_api.create_role(role['id'], role)
+
+ base_collection_url = (
+ '/OS-INHERIT/domains/%(domain_id)s/users/%(user_id)s/roles' % {
+ 'domain_id': self.domain_id,
+ 'user_id': self.user['id']})
+ member_url = '%(collection_url)s/%(role_id)s/inherited_to_projects' % {
+ 'collection_url': base_collection_url,
+ 'role_id': role['id']}
+ collection_url = base_collection_url + '/inherited_to_projects'
+
+ self.put(member_url, expected_status=404)
+ self.head(member_url, expected_status=404)
+ self.get(collection_url, expected_status=404)
+ self.delete(member_url, expected_status=404)
+
+ def test_list_role_assignments_for_inherited_domain_grants(self):
+ """Call ``GET /role_assignments with inherited domain grants``.
+
+ Test Plan:
+ - Create 4 roles
+ - Create a domain with a user and two projects
+ - Assign two direct roles to project1
+ - Assign a spoiler role to project2
+ - Issue the URL to add inherited role to the domain
+ - Issue the URL to check it is indeed on the domain
+ - Issue the URL to check effective roles on project1 - this
+ should return 3 roles.
+
+ """
+ role_list = []
+ for _ in range(4):
+ role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex}
+ self.assignment_api.create_role(role['id'], role)
+ role_list.append(role)
+
+ domain = self.new_domain_ref()
+ self.identity_api.create_domain(domain['id'], domain)
+ user1 = self.new_user_ref(
+ domain_id=domain['id'])
+ user1['password'] = uuid.uuid4().hex
+ self.identity_api.create_user(user1['id'], user1)
+ project1 = self.new_project_ref(
+ domain_id=domain['id'])
+ self.assignment_api.create_project(project1['id'], project1)
+ project2 = self.new_project_ref(
+ domain_id=domain['id'])
+ self.assignment_api.create_project(project2['id'], project2)
+ # Add some roles to the project
+ self.assignment_api.add_role_to_user_and_project(
+ user1['id'], project1['id'], role_list[0]['id'])
+ self.assignment_api.add_role_to_user_and_project(
+ user1['id'], project1['id'], role_list[1]['id'])
+ # ..and one on a different project as a spoiler
+ self.assignment_api.add_role_to_user_and_project(
+ user1['id'], project2['id'], role_list[2]['id'])
+
+ # Now create our inherited role on the domain
+ base_collection_url = (
+ '/OS-INHERIT/domains/%(domain_id)s/users/%(user_id)s/roles' % {
+ 'domain_id': domain['id'],
+ 'user_id': user1['id']})
+ member_url = '%(collection_url)s/%(role_id)s/inherited_to_projects' % {
+ 'collection_url': base_collection_url,
+ 'role_id': role_list[3]['id']}
+ collection_url = base_collection_url + '/inherited_to_projects'
+
+ self.put(member_url)
+ self.head(member_url)
+ r = self.get(collection_url)
+ self.assertValidRoleListResponse(r, ref=role_list[3])
+ self.assertIn(collection_url, r.result['links']['self'])
+
+ # Now use the list domain role assignments api to check if this
+ # is included
+ collection_url = (
+ '/role_assignments?user.id=%(user_id)s'
+ '&scope.domain.id=%(domain_id)s' % {
+ 'user_id': user1['id'],
+ 'domain_id': domain['id']})
+ r = self.get(collection_url)
+ self.assertValidRoleAssignmentListResponse(r)
+ self.assertEqual(len(r.result.get('role_assignments')), 1)
+ ud_url, ud_entity = _build_role_assignment_url_and_entity(
+ domain_id=domain['id'], user_id=user1['id'],
+ role_id=role_list[3]['id'], inherited_to_projects=True)
+ self.assertRoleAssignmentInListResponse(r, ud_entity, link_url=ud_url)
+
+ # Now ask for effective list role assignments - the role should
+ # turn into a project role, along with the two direct roles that are
+ # on the project
+ collection_url = (
+ '/role_assignments?effective&user.id=%(user_id)s'
+ '&scope.project.id=%(project_id)s' % {
+ 'user_id': user1['id'],
+ 'project_id': project1['id']})
+ r = self.get(collection_url)
+ self.assertValidRoleAssignmentListResponse(r)
+ self.assertEqual(len(r.result.get('role_assignments')), 3)
+ # An effective role for an inherited role will be a project
+ # entity, with a domain link to the inherited assignment
+ unused, up_entity = _build_role_assignment_url_and_entity(
+ project_id=project1['id'], user_id=user1['id'],
+ role_id=role_list[3]['id'])
+ ud_url, unused = _build_role_assignment_url_and_entity(
+ domain_id=domain['id'], user_id=user1['id'],
+ role_id=role_list[3]['id'], inherited_to_projects=True)
+ self.assertRoleAssignmentInListResponse(r, up_entity, link_url=ud_url)
+
+ def test_list_role_assignments_for_disabled_inheritance_extension(self):
+ """Call ``GET /role_assignments with inherited domain grants``.
+
+ Test Plan:
+ - Issue the URL to add inherited role to the domain
+ - Issue the URL to check effective roles on project include the
+ inherited role
+ - Disable the extension
+ - Re-check the effective roles, proving the inherited role no longer
+ shows up.
+
+ """
+
+ role_list = []
+ for _ in range(4):
+ role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex}
+ self.assignment_api.create_role(role['id'], role)
+ role_list.append(role)
+
+ domain = self.new_domain_ref()
+ self.identity_api.create_domain(domain['id'], domain)
+ user1 = self.new_user_ref(
+ domain_id=domain['id'])
+ user1['password'] = uuid.uuid4().hex
+ self.identity_api.create_user(user1['id'], user1)
+ project1 = self.new_project_ref(
+ domain_id=domain['id'])
+ self.assignment_api.create_project(project1['id'], project1)
+ project2 = self.new_project_ref(
+ domain_id=domain['id'])
+ self.assignment_api.create_project(project2['id'], project2)
+ # Add some roles to the project
+ self.assignment_api.add_role_to_user_and_project(
+ user1['id'], project1['id'], role_list[0]['id'])
+ self.assignment_api.add_role_to_user_and_project(
+ user1['id'], project1['id'], role_list[1]['id'])
+ # ..and one on a different project as a spoiler
+ self.assignment_api.add_role_to_user_and_project(
+ user1['id'], project2['id'], role_list[2]['id'])
+
+ # Now create our inherited role on the domain
+ base_collection_url = (
+ '/OS-INHERIT/domains/%(domain_id)s/users/%(user_id)s/roles' % {
+ 'domain_id': domain['id'],
+ 'user_id': user1['id']})
+ member_url = '%(collection_url)s/%(role_id)s/inherited_to_projects' % {
+ 'collection_url': base_collection_url,
+ 'role_id': role_list[3]['id']}
+ collection_url = base_collection_url + '/inherited_to_projects'
+
+ self.put(member_url)
+ self.head(member_url)
+ r = self.get(collection_url)
+ self.assertValidRoleListResponse(r, ref=role_list[3])
+ self.assertIn(collection_url, r.result['links']['self'])
+
+ # Get effective list role assignments - the role should
+ # turn into a project role, along with the two direct roles that are
+ # on the project
+ collection_url = (
+ '/role_assignments?effective&user.id=%(user_id)s'
+ '&scope.project.id=%(project_id)s' % {
+ 'user_id': user1['id'],
+ 'project_id': project1['id']})
+ r = self.get(collection_url)
+ self.assertValidRoleAssignmentListResponse(r)
+ self.assertEqual(len(r.result.get('role_assignments')), 3)
+
+ unused, up_entity = _build_role_assignment_url_and_entity(
+ project_id=project1['id'], user_id=user1['id'],
+ role_id=role_list[3]['id'])
+ ud_url, unused = _build_role_assignment_url_and_entity(
+ domain_id=domain['id'], user_id=user1['id'],
+ role_id=role_list[3]['id'], inherited_to_projects=True)
+ self.assertRoleAssignmentInListResponse(r, up_entity, link_url=ud_url)
+
+ # Disable the extension and re-check the list, the role inherited
+ # from the project should no longer show up
+ self.opt_in_group('os_inherit', enabled=False)
+ r = self.get(collection_url)
+ self.assertValidRoleAssignmentListResponse(r)
+ self.assertEqual(len(r.result.get('role_assignments')), 2)
+
+ unused, up_entity = _build_role_assignment_url_and_entity(
+ project_id=project1['id'], user_id=user1['id'],
+ role_id=role_list[3]['id'])
+ ud_url, unused = _build_role_assignment_url_and_entity(
+ domain_id=domain['id'], user_id=user1['id'],
+ role_id=role_list[3]['id'], inherited_to_projects=True)
+ self.assertRoleAssignmentNotInListResponse(r, up_entity,
+ link_url=ud_url)
+
+ def test_list_role_assignments_for_inherited_group_domain_grants(self):
+ """Call ``GET /role_assignments with inherited group domain grants``.
+
+ Test Plan:
+ - Create 4 roles
+ - Create a domain with a user and two projects
+ - Assign two direct roles to project1
+ - Assign a spoiler role to project2
+ - Issue the URL to add inherited role to the domain
+ - Issue the URL to check it is indeed on the domain
+ - Issue the URL to check effective roles on project1 - this
+ should return 3 roles.
+
+ """
+ role_list = []
+ for _ in range(4):
+ role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex}
+ self.assignment_api.create_role(role['id'], role)
+ role_list.append(role)
+
+ domain = self.new_domain_ref()
+ self.identity_api.create_domain(domain['id'], domain)
+ user1 = self.new_user_ref(
+ domain_id=domain['id'])
+ user1['password'] = uuid.uuid4().hex
+ self.identity_api.create_user(user1['id'], user1)
+ user2 = self.new_user_ref(
+ domain_id=domain['id'])
+ user2['password'] = uuid.uuid4().hex
+ self.identity_api.create_user(user2['id'], user2)
+ group1 = self.new_group_ref(
+ domain_id=domain['id'])
+ self.identity_api.create_group(group1['id'], group1)
+ self.identity_api.add_user_to_group(user1['id'],
+ group1['id'])
+ self.identity_api.add_user_to_group(user2['id'],
+ group1['id'])
+ project1 = self.new_project_ref(
+ domain_id=domain['id'])
+ self.assignment_api.create_project(project1['id'], project1)
+ project2 = self.new_project_ref(
+ domain_id=domain['id'])
+ self.assignment_api.create_project(project2['id'], project2)
+ # Add some roles to the project
+ self.assignment_api.add_role_to_user_and_project(
+ user1['id'], project1['id'], role_list[0]['id'])
+ self.assignment_api.add_role_to_user_and_project(
+ user1['id'], project1['id'], role_list[1]['id'])
+ # ..and one on a different project as a spoiler
+ self.assignment_api.add_role_to_user_and_project(
+ user1['id'], project2['id'], role_list[2]['id'])
+
+ # Now create our inherited role on the domain
+ base_collection_url = (
+ '/OS-INHERIT/domains/%(domain_id)s/groups/%(group_id)s/roles' % {
+ 'domain_id': domain['id'],
+ 'group_id': group1['id']})
+ member_url = '%(collection_url)s/%(role_id)s/inherited_to_projects' % {
+ 'collection_url': base_collection_url,
+ 'role_id': role_list[3]['id']}
+ collection_url = base_collection_url + '/inherited_to_projects'
+
+ self.put(member_url)
+ self.head(member_url)
+ r = self.get(collection_url)
+ self.assertValidRoleListResponse(r, ref=role_list[3])
+ self.assertIn(collection_url, r.result['links']['self'])
+
+ # Now use the list domain role assignments api to check if this
+ # is included
+ collection_url = (
+ '/role_assignments?group.id=%(group_id)s'
+ '&scope.domain.id=%(domain_id)s' % {
+ 'group_id': group1['id'],
+ 'domain_id': domain['id']})
+ r = self.get(collection_url)
+ self.assertValidRoleAssignmentListResponse(r)
+ self.assertEqual(len(r.result.get('role_assignments')), 1)
+ gd_url, gd_entity = _build_role_assignment_url_and_entity(
+ domain_id=domain['id'], group_id=group1['id'],
+ role_id=role_list[3]['id'], inherited_to_projects=True)
+ self.assertRoleAssignmentInListResponse(r, gd_entity, link_url=gd_url)
+
+ # Now ask for effective list role assignments - the role should
+ # turn into a user project role, along with the two direct roles
+ # that are on the project
+ collection_url = (
+ '/role_assignments?effective&user.id=%(user_id)s'
+ '&scope.project.id=%(project_id)s' % {
+ 'user_id': user1['id'],
+ 'project_id': project1['id']})
+ r = self.get(collection_url)
+ self.assertValidRoleAssignmentListResponse(r)
+ self.assertEqual(len(r.result.get('role_assignments')), 3)
+ # An effective role for an inherited role will be a project
+ # entity, with a domain link to the inherited assignment
+ unused, up_entity = _build_role_assignment_url_and_entity(
+ project_id=project1['id'], user_id=user1['id'],
+ role_id=role_list[3]['id'])
+ gd_url, unused = _build_role_assignment_url_and_entity(
+ domain_id=domain['id'], group_id=group1['id'],
+ role_id=role_list[3]['id'], inherited_to_projects=True)
+ self.assertRoleAssignmentInListResponse(r, up_entity, link_url=gd_url)
+
+ def test_filtered_role_assignments_for_inherited_grants(self):
+ """Call ``GET /role_assignments?scope.OS-INHERIT:inherited_to``.
+
+ Test Plan:
+ - Create 5 roles
+ - Create a domain with a user, group and two projects
+ - Assign three direct spoiler roles to projects
+ - Issue the URL to add an inherited user role to the domain
+ - Issue the URL to add an inherited group role to the domain
+ - Issue the URL to filter by inherited roles - this should
+ return just the 2 inherited roles.
+
+ """
+ role_list = []
+ for _ in range(5):
+ role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex}
+ self.assignment_api.create_role(role['id'], role)
+ role_list.append(role)
+
+ domain = self.new_domain_ref()
+ self.identity_api.create_domain(domain['id'], domain)
+ user1 = self.new_user_ref(
+ domain_id=domain['id'])
+ user1['password'] = uuid.uuid4().hex
+ self.identity_api.create_user(user1['id'], user1)
+ group1 = self.new_group_ref(
+ domain_id=domain['id'])
+ self.identity_api.create_group(group1['id'], group1)
+ project1 = self.new_project_ref(
+ domain_id=domain['id'])
+ self.assignment_api.create_project(project1['id'], project1)
+ project2 = self.new_project_ref(
+ domain_id=domain['id'])
+ self.assignment_api.create_project(project2['id'], project2)
+ # Add some spoiler roles to the projects
+ self.assignment_api.add_role_to_user_and_project(
+ user1['id'], project1['id'], role_list[0]['id'])
+ self.assignment_api.add_role_to_user_and_project(
+ user1['id'], project2['id'], role_list[1]['id'])
+ # Create a non-inherited role as a spoiler
+ self.assignment_api.create_grant(
+ role_list[2]['id'], user_id=user1['id'], domain_id=domain['id'])
+
+ # Now create two inherited roles on the domain, one for a user
+ # and one for a domain
+ base_collection_url = (
+ '/OS-INHERIT/domains/%(domain_id)s/users/%(user_id)s/roles' % {
+ 'domain_id': domain['id'],
+ 'user_id': user1['id']})
+ member_url = '%(collection_url)s/%(role_id)s/inherited_to_projects' % {
+ 'collection_url': base_collection_url,
+ 'role_id': role_list[3]['id']}
+ collection_url = base_collection_url + '/inherited_to_projects'
+
+ self.put(member_url)
+ self.head(member_url)
+ r = self.get(collection_url)
+ self.assertValidRoleListResponse(r, ref=role_list[3])
+ self.assertIn(collection_url, r.result['links']['self'])
+
+ base_collection_url = (
+ '/OS-INHERIT/domains/%(domain_id)s/groups/%(group_id)s/roles' % {
+ 'domain_id': domain['id'],
+ 'group_id': group1['id']})
+ member_url = '%(collection_url)s/%(role_id)s/inherited_to_projects' % {
+ 'collection_url': base_collection_url,
+ 'role_id': role_list[4]['id']}
+ collection_url = base_collection_url + '/inherited_to_projects'
+
+ self.put(member_url)
+ self.head(member_url)
+ r = self.get(collection_url)
+ self.assertValidRoleListResponse(r, ref=role_list[4])
+ self.assertIn(collection_url, r.result['links']['self'])
+
+ # Now use the list role assignments api to get a list of inherited
+ # roles on the domain - should get back the two roles
+ collection_url = (
+ '/role_assignments?scope.OS-INHERIT:inherited_to=projects')
+ r = self.get(collection_url)
+ self.assertValidRoleAssignmentListResponse(r)
+ self.assertEqual(len(r.result.get('role_assignments')), 2)
+ ud_url, ud_entity = _build_role_assignment_url_and_entity(
+ domain_id=domain['id'], user_id=user1['id'],
+ role_id=role_list[3]['id'], inherited_to_projects=True)
+ gd_url, gd_entity = _build_role_assignment_url_and_entity(
+ domain_id=domain['id'], group_id=group1['id'],
+ role_id=role_list[4]['id'], inherited_to_projects=True)
+ self.assertRoleAssignmentInListResponse(r, ud_entity, link_url=ud_url)
+ self.assertRoleAssignmentInListResponse(r, gd_entity, link_url=gd_url)
diff --git a/tests/test_versions.py b/tests/test_versions.py
index 58ace878..c5864c37 100644
--- a/tests/test_versions.py
+++ b/tests/test_versions.py
@@ -176,7 +176,6 @@ class VersionTestCase(test.TestCase):
self.assertEqual(data, expected)
def test_public_version_v3(self):
- print CONF.public_port
client = self.client(self.public_app)
resp = client.get('/v3/')
self.assertEqual(resp.status_int, 200)
diff --git a/tests/test_wsgi.py b/tests/test_wsgi.py
index c73212c8..003f7571 100644
--- a/tests/test_wsgi.py
+++ b/tests/test_wsgi.py
@@ -14,8 +14,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import webob
-
from keystone import test
from keystone.common import wsgi
@@ -34,7 +32,7 @@ class BaseWSGITest(test.TestCase):
super(BaseWSGITest, self).setUp()
def _make_request(self, url='/'):
- req = webob.Request.blank(url)
+ req = wsgi.Request.blank(url)
args = {'action': 'index', 'controller': None}
req.environ['wsgiorg.routing_args'] = [None, args]
return req
@@ -125,6 +123,32 @@ class ApplicationTest(BaseWSGITest):
self.assertEqual(resp.headers.get('Content-Length'), '0')
self.assertEqual(resp.headers.get('Content-Type'), None)
+ def test_application_local_config(self):
+ class FakeApp(wsgi.Application):
+ def __init__(self, *args, **kwargs):
+ self.kwargs = kwargs
+
+ app = FakeApp.factory({}, testkey="test")
+ self.assertIn("testkey", app.kwargs)
+ self.assertEquals("test", app.kwargs["testkey"])
+
+ def test_render_exception(self):
+ e = exception.Unauthorized(message=u'\u7f51\u7edc')
+ resp = wsgi.render_exception(e)
+ self.assertEqual(resp.status_int, 401)
+
+
+class ExtensionRouterTest(BaseWSGITest):
+ def test_extensionrouter_local_config(self):
+ class FakeRouter(wsgi.ExtensionRouter):
+ def __init__(self, *args, **kwargs):
+ self.kwargs = kwargs
+
+ factory = FakeRouter.factory({}, testkey="test")
+ app = factory(self.app)
+ self.assertIn("testkey", app.kwargs)
+ self.assertEquals("test", app.kwargs["testkey"])
+
class MiddlewareTest(BaseWSGITest):
def test_middleware_request(self):
diff --git a/tests/tmp/.gitkeep b/tests/tmp/.gitkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/tests/tmp/.gitkeep
diff --git a/tools/install_venv_common.py b/tools/install_venv_common.py
index 42a44e8c..f428c1e0 100644
--- a/tools/install_venv_common.py
+++ b/tools/install_venv_common.py
@@ -34,12 +34,13 @@ import sys
class InstallVenv(object):
- def __init__(self, root, venv, pip_requires, test_requires, py_version,
+ def __init__(self, root, venv, requirements,
+ test_requirements, py_version,
project):
self.root = root
self.venv = venv
- self.pip_requires = pip_requires
- self.test_requires = test_requires
+ self.requirements = requirements
+ self.test_requirements = test_requirements
self.py_version = py_version
self.project = project
@@ -75,11 +76,13 @@ class InstallVenv(object):
def get_distro(self):
if (os.path.exists('/etc/fedora-release') or
os.path.exists('/etc/redhat-release')):
- return Fedora(self.root, self.venv, self.pip_requires,
- self.test_requires, self.py_version, self.project)
+ return Fedora(
+ self.root, self.venv, self.requirements,
+ self.test_requirements, self.py_version, self.project)
else:
- return Distro(self.root, self.venv, self.pip_requires,
- self.test_requires, self.py_version, self.project)
+ return Distro(
+ self.root, self.venv, self.requirements,
+ self.test_requirements, self.py_version, self.project)
def check_dependencies(self):
self.get_distro().install_virtualenv()
@@ -98,11 +101,6 @@ class InstallVenv(object):
else:
self.run_command(['virtualenv', '-q', self.venv])
print('done.')
- print('Installing pip in venv...', end=' ')
- if not self.run_command(['tools/with_venv.sh', 'easy_install',
- 'pip>1.0']).strip():
- self.die("Failed to install pip.")
- print('done.')
else:
print("venv already exists...")
pass
@@ -116,20 +114,12 @@ class InstallVenv(object):
print('Installing dependencies with pip (this can take a while)...')
# First things first, make sure our venv has the latest pip and
- # distribute.
- # NOTE: we keep pip at version 1.1 since the most recent version causes
- # the .venv creation to fail. See:
- # https://bugs.launchpad.net/nova/+bug/1047120
- self.pip_install('pip==1.1')
- self.pip_install('distribute')
-
- # Install greenlet by hand - just listing it in the requires file does
- # not
- # get it installed in the right order
- self.pip_install('greenlet')
-
- self.pip_install('-r', self.pip_requires)
- self.pip_install('-r', self.test_requires)
+ # setuptools.
+ self.pip_install('pip>=1.3')
+ self.pip_install('setuptools')
+
+ self.pip_install('-r', self.requirements)
+ self.pip_install('-r', self.test_requirements)
def post_process(self):
self.get_distro().post_process()
diff --git a/tox.ini b/tox.ini
index 93d8f186..1fe184ea 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
[tox]
-envlist = py26,py27,pep8
+envlist = py26,py27,py33,pep8
[testenv]
setenv = VIRTUAL_ENV={envdir}