summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.zuul.yaml2
-rw-r--r--README.rst2
-rw-r--r--doc/requirements.txt3
-rw-r--r--doc/source/conf.py19
-rw-r--r--keystonemiddleware/auth_token/__init__.py8
-rw-r--r--keystonemiddleware/auth_token/_identity.py35
-rw-r--r--keystonemiddleware/auth_token/_request.py24
-rw-r--r--keystonemiddleware/ec2_token.py9
-rw-r--r--keystonemiddleware/locale/en_GB/LC_MESSAGES/keystonemiddleware.po16
-rw-r--r--keystonemiddleware/locale/ko_KR/LC_MESSAGES/keystonemiddleware.po6
-rw-r--r--keystonemiddleware/tests/unit/auth_token/test_auth_token_middleware.py261
-rw-r--r--keystonemiddleware/tests/unit/auth_token/test_request.py4
-rw-r--r--keystonemiddleware/tests/unit/auth_token/test_user_auth_plugin.py66
-rw-r--r--keystonemiddleware/tests/unit/test_ec2_token_middleware.py17
-rw-r--r--releasenotes/notes/ec2-v2-removal-6a886210cbc9d3e9.yaml7
-rw-r--r--releasenotes/notes/removed-as-of-ussuri-4e1ea485ba8801c9.yaml7
-rw-r--r--releasenotes/source/index.rst1
-rw-r--r--releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po215
-rw-r--r--releasenotes/source/train.rst6
-rw-r--r--tox.ini12
20 files changed, 312 insertions, 408 deletions
diff --git a/.zuul.yaml b/.zuul.yaml
index 883bc2b..2427b9b 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -3,7 +3,7 @@
- openstack-cover-jobs
- openstack-lower-constraints-jobs
- openstack-python-jobs
- - openstack-python3-train-jobs
+ - openstack-python3-ussuri-jobs
- publish-openstack-docs-pti
- check-requirements
- lib-forward-testing
diff --git a/README.rst b/README.rst
index 1130411..40ea782 100644
--- a/README.rst
+++ b/README.rst
@@ -28,7 +28,7 @@ For information on contributing, see ``CONTRIBUTING.rst``.
* License: Apache License, Version 2.0
* Documentation: https://docs.openstack.org/keystonemiddleware/latest/
-* Source: https://git.openstack.org/cgit/openstack/keystonemiddleware
+* Source: https://opendev.org/openstack/keystonemiddleware
* Bugs: https://bugs.launchpad.net/keystonemiddleware
* Release notes: https://docs.openstack.org/releasenotes/keystonemiddleware/
diff --git a/doc/requirements.txt b/doc/requirements.txt
index 42dda5b..ddd05be 100644
--- a/doc/requirements.txt
+++ b/doc/requirements.txt
@@ -10,6 +10,9 @@ sphinx!=1.6.6,!=1.6.7,>=1.6.2,<2.0.0;python_version=='2.7' # BSD
sphinx!=1.6.6,!=1.6.7,!=2.1.0,>=1.6.2;python_version>='3.4' # BSD
sphinxcontrib-apidoc>=0.2.0 # BSD
+# PDF Docs
+sphinxcontrib-svg2pdfconverter>=0.1.0 # BSD
+
# For autodoc builds
mock>=2.0.0 # BSD
oslotest>=3.2.0 # Apache-2.0
diff --git a/doc/source/conf.py b/doc/source/conf.py
index ccea01f..4428242 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -42,6 +42,7 @@ extensions = ['sphinx.ext.todo',
'openstackdocstheme',
'oslo_config.sphinxconfiggen',
'sphinxcontrib.apidoc',
+ 'sphinxcontrib.rsvgconverter',
]
# sphinxcontrib.apidoc options
@@ -200,12 +201,24 @@ htmlhelp_basename = 'keystonemiddlewaredoc'
# (source start file, target name, title, author, documentclass [howto/manual])
# .
latex_documents = [
- ('index', 'keystonmiddleware.tex',
- 'keystonemiddleware Documentation',
- 'Nebula Inc, based on work by Rackspace and Jacob Kaplan-Moss',
+ ('index', 'doc-keystonemiddleware.tex',
+ u'keystonemiddleware Documentation',
+ u'Openstack Developers',
'manual'),
]
+# Disable usage of xindy https://bugzilla.redhat.com/show_bug.cgi?id=1643664
+latex_use_xindy = False
+
+latex_domain_indices = False
+
+latex_elements = {
+ 'extraclassoptions': 'openany',
+ 'makeindex': '',
+ 'printindex': '',
+ 'preamble': r'\setcounter{tocdepth}{3}',
+ 'maxlistdepth': 10,
+}
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
diff --git a/keystonemiddleware/auth_token/__init__.py b/keystonemiddleware/auth_token/__init__.py
index b29b63a..d961f59 100644
--- a/keystonemiddleware/auth_token/__init__.py
+++ b/keystonemiddleware/auth_token/__init__.py
@@ -282,14 +282,14 @@ def _path_matches(request_path, path_pattern):
# The fnmatch module doesn't provide the ability to match * versus **,
# so convert to regex.
token_regex = (r'(?P<tag>{[^}]*})|' # {tag} # nosec
- '(?P<wild>\*(?=$|[^\*]))|' # *
- '(?P<rec_wild>\*\*)|' # **
- '(?P<literal>[^{}\*])') # anything else
+ r'(?P<wild>\*(?=$|[^\*]))|' # *
+ r'(?P<rec_wild>\*\*)|' # **
+ r'(?P<literal>[^{}\*])') # anything else
path_regex = ''
for match in re.finditer(token_regex, path_pattern):
token = match.groupdict()
if token['tag'] or token['wild']:
- path_regex += '[^\/]+'
+ path_regex += r'[^\/]+'
if token['rec_wild']:
path_regex += '.*'
if token['literal']:
diff --git a/keystonemiddleware/auth_token/_identity.py b/keystonemiddleware/auth_token/_identity.py
index 49bdf9a..53d3819 100644
--- a/keystonemiddleware/auth_token/_identity.py
+++ b/keystonemiddleware/auth_token/_identity.py
@@ -13,7 +13,6 @@
from keystoneauth1 import discover
from keystoneauth1 import exceptions as ksa_exceptions
from keystoneauth1 import plugin
-from keystoneclient.v2_0 import client as v2_client
from keystoneclient.v3 import client as v3_client
from six.moves import urllib
@@ -37,25 +36,6 @@ class _RequestStrategy(object):
pass
-class _V2RequestStrategy(_RequestStrategy):
-
- AUTH_VERSION = (2, 0)
-
- def __init__(self, adap, **kwargs):
- super(_V2RequestStrategy, self).__init__(adap, **kwargs)
- self._client = v2_client.Client(session=adap)
-
- def verify_token(self, token, allow_expired=False):
- # NOTE(jamielennox): allow_expired is ignored on V2
- auth_ref = self._client.tokens.validate_access_info(token)
-
- if not auth_ref:
- msg = _('Failed to fetch token data from identity server')
- raise ksm_exceptions.InvalidToken(msg)
-
- return {'access': auth_ref}
-
-
class _V3RequestStrategy(_RequestStrategy):
AUTH_VERSION = (3, 0)
@@ -81,7 +61,7 @@ class _V3RequestStrategy(_RequestStrategy):
return {'token': auth_ref}
-_REQUEST_STRATEGIES = [_V3RequestStrategy, _V2RequestStrategy]
+_REQUEST_STRATEGIES = [_V3RequestStrategy]
class IdentityServer(object):
@@ -137,13 +117,12 @@ class IdentityServer(object):
def _get_strategy_class(self):
if self._requested_auth_version:
- # A specific version was requested.
- if discover.version_match(_V3RequestStrategy.AUTH_VERSION,
- self._requested_auth_version):
- return _V3RequestStrategy
-
- # The version isn't v3 so we don't know what to do. Just assume V2.
- return _V2RequestStrategy
+ if not discover.version_match(_V3RequestStrategy.AUTH_VERSION,
+ self._requested_auth_interface):
+ self._LOG.info('A version other than v3 was requested: %s',
+ self._requested_auth_interface)
+ # Return v3, even if the request is unknown
+ return _V3RequestStrategy
# Specific version was not requested then we fall through to
# discovering available versions from the server
diff --git a/keystonemiddleware/auth_token/_request.py b/keystonemiddleware/auth_token/_request.py
index 269c3d3..cba28bf 100644
--- a/keystonemiddleware/auth_token/_request.py
+++ b/keystonemiddleware/auth_token/_request.py
@@ -16,20 +16,16 @@ from oslo_serialization import jsonutils
import webob
-def _v3_to_v2_catalog(catalog):
- """Convert a catalog to v2 format.
-
- X_SERVICE_CATALOG must be specified in v2 format. If you get a token
- that is in v3 convert it.
- """
- v2_services = []
+def _normalize_catalog(catalog):
+ """Convert a catalog to a compatible format."""
+ services = []
for v3_service in catalog:
# first copy over the entries we allow for the service
- v2_service = {'type': v3_service['type']}
+ service = {'type': v3_service['type']}
try:
- v2_service['name'] = v3_service['name']
+ service['name'] = v3_service['name']
except KeyError: # nosec
- # v3 service doesn't have a name, so v2_service doesn't either.
+ # v3 service doesn't have a name, move on.
pass
# now convert the endpoints. Because in v3 we specify region per
@@ -47,10 +43,10 @@ def _v3_to_v2_catalog(catalog):
interface_name = v3_endpoint['interface'].lower() + 'URL'
region[interface_name] = v3_endpoint['url']
- v2_service['endpoints'] = list(regions.values())
- v2_services.append(v2_service)
+ service['endpoints'] = list(regions.values())
+ services.append(service)
- return v2_services
+ return services
def _is_admin_project(auth_ref):
@@ -194,7 +190,7 @@ class _AuthTokenRequest(webob.Request):
catalog = auth_ref.service_catalog.catalog
if auth_ref.version == 'v3':
- catalog = _v3_to_v2_catalog(catalog)
+ catalog = _normalize_catalog(catalog)
c = jsonutils.dumps(catalog)
self.headers[self._SERVICE_CATALOG_HEADER] = c
diff --git a/keystonemiddleware/ec2_token.py b/keystonemiddleware/ec2_token.py
index 5fe6096..faa5968 100644
--- a/keystonemiddleware/ec2_token.py
+++ b/keystonemiddleware/ec2_token.py
@@ -31,7 +31,7 @@ from keystonemiddleware.i18n import _
keystone_ec2_opts = [
cfg.StrOpt('url',
- default='http://localhost:5000/v2.0/ec2tokens',
+ default='http://localhost:5000/v3/ec2tokens',
help='URL to get token from ec2 request.'),
cfg.StrOpt('keyfile',
help='Required if EC2 server requires client certificate.'),
@@ -185,13 +185,8 @@ class EC2Token(object):
msg = _('Error response from keystone: %s') % response.reason
self._logger.debug(msg)
return self._ec2_error_response("AuthFailure", msg)
- result = response.json()
try:
- if 'token' in result:
- # NOTE(andrey-mp): response from keystone v3
- token_id = response.headers['x-subject-token']
- else:
- token_id = result['access']['token']['id']
+ token_id = response.headers['x-subject-token']
except (AttributeError, KeyError):
msg = _("Failure parsing response from keystone")
self._logger.exception(msg)
diff --git a/keystonemiddleware/locale/en_GB/LC_MESSAGES/keystonemiddleware.po b/keystonemiddleware/locale/en_GB/LC_MESSAGES/keystonemiddleware.po
index 0f043bf..ee8f5c3 100644
--- a/keystonemiddleware/locale/en_GB/LC_MESSAGES/keystonemiddleware.po
+++ b/keystonemiddleware/locale/en_GB/LC_MESSAGES/keystonemiddleware.po
@@ -3,7 +3,7 @@ msgid ""
msgstr ""
"Project-Id-Version: keystonemiddleware VERSION\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
-"POT-Creation-Date: 2018-04-21 04:01+0000\n"
+"POT-Creation-Date: 2019-12-21 02:49+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -27,10 +27,6 @@ msgstr "Error response from Keystone: %s"
msgid "Failed to fetch token data from identity server"
msgstr "Failed to fetch token data from identity server"
-#, python-format
-msgid "Failed to fetch token revocation list: %d"
-msgstr "Failed to fetch token revocation list: %d"
-
msgid "Failure parsing response from keystone"
msgstr "Failure parsing response from Keystone"
@@ -46,9 +42,6 @@ msgstr "Invalid version asked for in auth_token plugin"
msgid "No compatible apis supported by server"
msgstr "No compatible APIs supported by server"
-msgid "Revocation list improperly formatted."
-msgstr "Revocation list improperly formatted."
-
msgid "Signature not provided"
msgstr "Signature not provided"
@@ -58,9 +51,6 @@ msgstr "The request you have made requires authentication."
msgid "Token authorization failed"
msgstr "Token authorisation failed"
-msgid "Token has been revoked"
-msgstr "Token has been revoked"
-
msgid "Unable to determine service tenancy."
msgstr "Unable to determine service tenancy."
@@ -70,7 +60,3 @@ msgid ""
msgstr ""
"memcache_secret_key must be defined when a memcache_security_strategy is "
"defined"
-
-#, python-format
-msgid "unable to access signing_dir %s"
-msgstr "unable to access signing_dir %s"
diff --git a/keystonemiddleware/locale/ko_KR/LC_MESSAGES/keystonemiddleware.po b/keystonemiddleware/locale/ko_KR/LC_MESSAGES/keystonemiddleware.po
index 02221ae..7a550a9 100644
--- a/keystonemiddleware/locale/ko_KR/LC_MESSAGES/keystonemiddleware.po
+++ b/keystonemiddleware/locale/ko_KR/LC_MESSAGES/keystonemiddleware.po
@@ -3,7 +3,7 @@ msgid ""
msgstr ""
"Project-Id-Version: keystonemiddleware VERSION\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
-"POT-Creation-Date: 2018-02-20 19:27+0000\n"
+"POT-Creation-Date: 2019-12-21 02:49+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -27,10 +27,6 @@ msgstr "keystone 오류 응답: %s"
msgid "Failed to fetch token data from identity server"
msgstr "인증 서버로부터 토큰 데이터를 가져올 수 없습니다"
-#, python-format
-msgid "Failed to fetch token revocation list: %d"
-msgstr "토큰 revocation 목록을 가져올 수 없습니다: %d"
-
msgid "Failure parsing response from keystone"
msgstr "keystone 응답 파싱 실패"
diff --git a/keystonemiddleware/tests/unit/auth_token/test_auth_token_middleware.py b/keystonemiddleware/tests/unit/auth_token/test_auth_token_middleware.py
index a09d269..9801540 100644
--- a/keystonemiddleware/tests/unit/auth_token/test_auth_token_middleware.py
+++ b/keystonemiddleware/tests/unit/auth_token/test_auth_token_middleware.py
@@ -22,7 +22,6 @@ from keystoneauth1 import exceptions as ksa_exceptions
from keystoneauth1 import fixture
from keystoneauth1 import loading
from keystoneauth1 import session
-from keystoneclient import exceptions as ksc_exceptions
import mock
import oslo_cache
from oslo_log import log as logging
@@ -590,7 +589,7 @@ class CommonAuthTokenMiddlewareTest(object):
return self.middleware._token_cache.get(token)
def test_memcache_set_invalid_uuid(self):
- invalid_uri = "%s/v2.0/tokens/invalid-token" % BASE_URI
+ invalid_uri = "%s/v3/tokens/invalid-token" % BASE_URI
self.requests_mock.get(invalid_uri, status_code=404)
token = 'invalid-token'
@@ -601,7 +600,7 @@ class CommonAuthTokenMiddlewareTest(object):
def test_memcache_hit_invalid_token(self):
token = 'invalid-token'
- invalid_uri = '%s/v2.0/tokens/invalid-token' % BASE_URI
+ invalid_uri = '%s/v3/tokens/invalid-token' % BASE_URI
self.requests_mock.get(invalid_uri, status_code=404)
# Call once to cache token's invalid state; verify it cached as such
@@ -1016,169 +1015,6 @@ def request_timeout_response(request, context):
"Request to https://host/token/path timed out")
-class v2AuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest,
- CommonAuthTokenMiddlewareTest,
- testresources.ResourcedTestCase):
- """v2 token specific tests.
-
- There are some differences between how the auth-token middleware handles
- v2 and v3 tokens over and above the token formats, namely:
-
- - A v3 keystone server will auto scope a token to a user's default project
- if no scope is specified. A v2 server assumes that the auth-token
- middleware will do that.
- - A v2 keystone server may issue a token without a catalog, even with a
- tenant
-
- The tests below were originally part of the generic AuthTokenMiddlewareTest
- class, but now, since they really are v2 specific, they are included here.
-
- """
-
- resources = [('examples', client_fixtures.EXAMPLES_RESOURCE)]
-
- def setUp(self):
- super(v2AuthTokenMiddlewareTest, self).setUp()
-
- self.token_dict = {
- 'uuid_token_default': self.examples.UUID_TOKEN_DEFAULT,
- 'uuid_token_unscoped': self.examples.UUID_TOKEN_UNSCOPED,
- 'uuid_token_bind': self.examples.UUID_TOKEN_BIND,
- 'uuid_token_unknown_bind': self.examples.UUID_TOKEN_UNKNOWN_BIND,
- 'uuid_service_token_default':
- self.examples.UUID_SERVICE_TOKEN_DEFAULT,
- }
-
- self.requests_mock.get(BASE_URI,
- json=VERSION_LIST_v2,
- status_code=300)
-
- self.requests_mock.post('%s/v2.0/tokens' % BASE_URI,
- text=FAKE_ADMIN_TOKEN)
-
- for token in (self.examples.UUID_TOKEN_DEFAULT,
- self.examples.UUID_TOKEN_UNSCOPED,
- self.examples.UUID_TOKEN_BIND,
- self.examples.UUID_TOKEN_UNKNOWN_BIND,
- self.examples.UUID_TOKEN_NO_SERVICE_CATALOG,
- self.examples.UUID_SERVICE_TOKEN_DEFAULT,):
- url = "%s/v2.0/tokens/%s" % (BASE_URI, token)
- text = self.examples.JSON_TOKEN_RESPONSES[token]
- self.requests_mock.get(url, text=text)
-
- url = '%s/v2.0/tokens/%s' % (BASE_URI, ERROR_TOKEN)
- self.requests_mock.get(url, text=network_error_response)
-
- url = '%s/v2.0/tokens/%s' % (BASE_URI, TIMEOUT_TOKEN)
- self.requests_mock.get(url, text=request_timeout_response)
-
- self.set_middleware()
-
- def assert_unscoped_default_tenant_auto_scopes(self, token):
- """Unscoped v2 requests with a default tenant should ``auto-scope``.
-
- The implied scope is the user's tenant ID.
-
- """
- resp = self.call_middleware(headers={'X-Auth-Token': token})
- self.assertEqual(FakeApp.SUCCESS, resp.body)
- self.assertIn('keystone.token_info', resp.request.environ)
-
- def assert_valid_last_url(self, token_id):
- self.assertLastPath("/v2.0/tokens/%s" % token_id)
-
- def test_default_tenant_uuid_token(self):
- self.assert_unscoped_default_tenant_auto_scopes(
- self.examples.UUID_TOKEN_DEFAULT)
-
- def assert_unscoped_token_receives_401(self, token):
- """Unscoped requests with no default tenant ID should be rejected."""
- resp = self.call_middleware(headers={'X-Auth-Token': token},
- expected_status=401)
- self.assertEqual('Keystone uri="https://keystone.example.com:1234"',
- resp.headers['WWW-Authenticate'])
-
- def test_request_prevent_service_catalog_injection(self):
- token = self.examples.UUID_TOKEN_NO_SERVICE_CATALOG
- resp = self.call_middleware(headers={'X-Service-Catalog': '[]',
- 'X-Auth-Token': token})
-
- self.assertFalse(resp.request.headers.get('X-Service-Catalog'))
- self.assertEqual(FakeApp.SUCCESS, resp.body)
-
- def test_user_plugin_token_properties(self):
- token = self.examples.UUID_TOKEN_DEFAULT
- token_data = self.examples.TOKEN_RESPONSES[token]
- service = self.examples.UUID_SERVICE_TOKEN_DEFAULT
-
- resp = self.call_middleware(headers={'X-Service-Catalog': '[]',
- 'X-Auth-Token': token,
- 'X-Service-Token': service})
-
- self.assertEqual(FakeApp.SUCCESS, resp.body)
-
- token_auth = resp.request.environ['keystone.token_auth']
-
- self.assertTrue(token_auth.has_user_token)
- self.assertTrue(token_auth.has_service_token)
-
- self.assertEqual(token_data.user_id, token_auth.user.user_id)
- self.assertEqual(token_data.tenant_id, token_auth.user.project_id)
-
- self.assertThat(token_auth.user.role_names, matchers.HasLength(2))
- self.assertIn('role1', token_auth.user.role_names)
- self.assertIn('role2', token_auth.user.role_names)
-
- self.assertIsNone(token_auth.user.trust_id)
- self.assertIsNone(token_auth.user.user_domain_id)
- self.assertIsNone(token_auth.user.project_domain_id)
-
- self.assertThat(token_auth.service.role_names, matchers.HasLength(2))
- self.assertIn('service', token_auth.service.role_names)
- self.assertIn('service_role2', token_auth.service.role_names)
-
- self.assertIsNone(token_auth.service.trust_id)
-
-
-class CrossVersionAuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest,
- testresources.ResourcedTestCase):
-
- resources = [('examples', client_fixtures.EXAMPLES_RESOURCE)]
-
- def test_valid_uuid_request_forced_to_2_0(self):
- """Test forcing auth_token to use lower api version.
-
- By installing the v3 http hander, auth_token will be get
- a version list that looks like a v3 server - from which it
- would normally chose v3.0 as the auth version. However, here
- we specify v2.0 in the configuration - which should force
- auth_token to use that version instead.
-
- """
- conf = {
- 'auth_version': 'v2.0'
- }
-
- self.requests_mock.get(BASE_URI,
- json=VERSION_LIST_v3,
- status_code=300)
-
- self.requests_mock.post('%s/v2.0/tokens' % BASE_URI,
- text=FAKE_ADMIN_TOKEN)
-
- token = self.examples.UUID_TOKEN_DEFAULT
- url = "%s/v2.0/tokens/%s" % (BASE_URI, token)
- text = self.examples.JSON_TOKEN_RESPONSES[token]
- self.requests_mock.get(url, text=text)
-
- self.set_middleware(conf=conf)
-
- # This tests will only work is auth_token has chosen to use the
- # lower, v2, api version
- self.call_middleware(headers={'X-Auth-Token': token})
- self.assertEqual(url, self.requests_mock.last_request.url)
-
-
class v3AuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest,
CommonAuthTokenMiddlewareTest,
testresources.ResourcedTestCase):
@@ -1190,19 +1026,7 @@ class v3AuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest,
This is done by configuring the AuthTokenMiddlewareTest class via
its Setup(), passing in v3 style data that will then be used by
- the tests themselves. This approach has been used to ensure we
- really are running the same tests for both v2 and v3 tokens.
-
- There a few additional specific test for v3 only:
-
- - We allow an unscoped token to be validated (as unscoped), where
- as for v2 tokens, the auth_token middleware is expected to try and
- auto-scope it (and fail if there is no default tenant)
- - Domain scoped tokens
-
- Since we don't specify an auth version for auth_token to use, by
- definition we are thefore implicitely testing that it will use
- the highest available auth version, i.e. v3.0
+ the tests themselves.
"""
@@ -1527,7 +1351,7 @@ class DelayedAuthTests(BaseAuthTokenMiddlewareTest):
if request.headers.get('X-Subject-Token') == ERROR_TOKEN:
msg = 'Network connection refused.'
- raise ksc_exceptions.ConnectionRefused(msg)
+ raise ksa_exceptions.ConnectFailure(msg)
# All others just fail
context.status_code = 404
@@ -1537,7 +1361,7 @@ class DelayedAuthTests(BaseAuthTokenMiddlewareTest):
body = uuid.uuid4().hex
www_authenticate_uri = 'http://local.test'
conf = {'delay_auth_decision': 'True',
- 'auth_version': 'v3.0',
+ 'auth_version': 'v3',
'www_authenticate_uri': www_authenticate_uri}
middleware = self.create_simple_middleware(status='401 Unauthorized',
@@ -1841,59 +1665,6 @@ class CommonCompositeAuthTests(object):
bind_level='required')
-class v2CompositeAuthTests(BaseAuthTokenMiddlewareTest,
- CommonCompositeAuthTests,
- testresources.ResourcedTestCase):
- """Test auth_token middleware with v2 token based composite auth.
-
- Execute the Composite auth class tests, but with the
- auth_token middleware configured to expect v2 tokens back from
- a keystone server.
- """
-
- resources = [('examples', client_fixtures.EXAMPLES_RESOURCE)]
-
- def setUp(self):
- super(v2CompositeAuthTests, self).setUp(
- expected_env=EXPECTED_V2_DEFAULT_SERVICE_ENV_RESPONSE,
- fake_app=CompositeFakeApp)
-
- uuid_token_default = self.examples.UUID_TOKEN_DEFAULT
- uuid_service_token_default = self.examples.UUID_SERVICE_TOKEN_DEFAULT
- uuid_token_bind = self.examples.UUID_TOKEN_BIND
- uuid_service_token_bind = self.examples.UUID_SERVICE_TOKEN_BIND
- self.token_dict = {
- 'uuid_token_default': uuid_token_default,
- 'uuid_service_token_default': uuid_service_token_default,
- 'uuid_token_bind': uuid_token_bind,
- 'uuid_service_token_bind': uuid_service_token_bind,
- }
-
- self.requests_mock.get(BASE_URI,
- json=VERSION_LIST_v2,
- status_code=300)
-
- self.requests_mock.post('%s/v2.0/tokens' % BASE_URI,
- text=FAKE_ADMIN_TOKEN)
-
- for token in (self.examples.UUID_TOKEN_DEFAULT,
- self.examples.UUID_SERVICE_TOKEN_DEFAULT,
- self.examples.UUID_TOKEN_BIND,
- self.examples.UUID_SERVICE_TOKEN_BIND):
- text = self.examples.JSON_TOKEN_RESPONSES[token]
- self.requests_mock.get('%s/v2.0/tokens/%s' % (BASE_URI, token),
- text=text)
-
- for invalid_uri in ("%s/v2.0/tokens/invalid-token" % BASE_URI,
- "%s/v2.0/tokens/invalid-service-token" % BASE_URI):
- self.requests_mock.get(invalid_uri, text='', status_code=404)
-
- self.token_expected_env = dict(EXPECTED_V2_DEFAULT_ENV_RESPONSE)
- self.service_token_expected_env = dict(
- EXPECTED_V2_DEFAULT_SERVICE_ENV_RESPONSE)
- self.set_middleware()
-
-
class v3CompositeAuthTests(BaseAuthTokenMiddlewareTest,
CommonCompositeAuthTests,
testresources.ResourcedTestCase):
@@ -1908,7 +1679,7 @@ class v3CompositeAuthTests(BaseAuthTokenMiddlewareTest,
def setUp(self):
super(v3CompositeAuthTests, self).setUp(
- auth_version='v3.0',
+ auth_version='v3',
fake_app=v3CompositeFakeApp)
uuid_token_default = self.examples.v3_UUID_TOKEN_DEFAULT
@@ -1951,7 +1722,7 @@ class v3CompositeAuthTests(BaseAuthTokenMiddlewareTest,
if token_id == ERROR_TOKEN:
msg = "Network connection refused."
- raise ksc_exceptions.ConnectionRefused(msg)
+ raise ksa_exceptions.ConnectFailure(msg)
elif token_id == TIMEOUT_TOKEN:
request_timeout_response(request, context)
@@ -1979,7 +1750,7 @@ class OtherTests(BaseAuthTokenMiddlewareTest):
self.call_middleware(headers={'X-Auth-Token': uuid.uuid4().hex},
expected_status=503)
- self.assertIn('versions [v3.0, v2.0]', self.logger.output)
+ self.assertIn('versions [v3.0]', self.logger.output)
def _assert_auth_version(self, conf_version, identity_server_version):
self.set_middleware(conf={'auth_version': conf_version})
@@ -1988,8 +1759,6 @@ class OtherTests(BaseAuthTokenMiddlewareTest):
identity_server.auth_version)
def test_micro_version(self):
- self._assert_auth_version('v2', (2, 0))
- self._assert_auth_version('v2.0', (2, 0))
self._assert_auth_version('v3', (3, 0))
self._assert_auth_version('v3.0', (3, 0))
self._assert_auth_version('v3.1', (3, 0))
@@ -2003,14 +1772,10 @@ class OtherTests(BaseAuthTokenMiddlewareTest):
self.requests_mock.get(BASE_URI, json=VERSION_LIST_v3, status_code=300)
self._assert_auth_version(None, (3, 0))
- # VERSION_LIST_v2 contains only v2 version elements
- self.requests_mock.get(BASE_URI, json=VERSION_LIST_v2, status_code=300)
- self._assert_auth_version(None, (2, 0))
-
def test_unsupported_auth_version(self):
- # If the requested version isn't supported we will use v2
- self._assert_auth_version('v1', (2, 0))
- self._assert_auth_version('v10', (2, 0))
+ # If the requested version isn't supported we will use v3
+ self._assert_auth_version('v1', (3, 0))
+ self._assert_auth_version('v10', (3, 0))
class AuthProtocolLoadingTests(BaseAuthTokenMiddlewareTest):
@@ -2020,9 +1785,7 @@ class AuthProtocolLoadingTests(BaseAuthTokenMiddlewareTest):
KEYSTONE_BASE_URL = 'http://keystone.url/prefix'
CRUD_URL = 'http://crud.url/prefix'
- # NOTE(jamielennox): use the /v2.0 prefix here because this is what's most
- # likely to be in the service catalog and we should be able to ignore it.
- KEYSTONE_URL = KEYSTONE_BASE_URL + '/v2.0'
+ KEYSTONE_URL = KEYSTONE_BASE_URL + '/v3'
def setUp(self):
super(AuthProtocolLoadingTests, self).setUp()
diff --git a/keystonemiddleware/tests/unit/auth_token/test_request.py b/keystonemiddleware/tests/unit/auth_token/test_request.py
index bd8a7b3..011525f 100644
--- a/keystonemiddleware/tests/unit/auth_token/test_request.py
+++ b/keystonemiddleware/tests/unit/auth_token/test_request.py
@@ -224,7 +224,7 @@ class CatalogConversionTests(utils.TestCase):
auth_ref = access.create(body=token)
catalog_data = auth_ref.service_catalog.catalog
- catalog = _request._v3_to_v2_catalog(catalog_data)
+ catalog = _request._normalize_catalog(catalog_data)
self.assertEqual(1, len(catalog))
service = catalog[0]
@@ -248,7 +248,7 @@ class CatalogConversionTests(utils.TestCase):
auth_ref = access.create(body=token)
catalog_data = auth_ref.service_catalog.catalog
- catalog = _request._v3_to_v2_catalog(catalog_data)
+ catalog = _request._normalize_catalog(catalog_data)
self.assertEqual(1, len(catalog))
service = catalog[0]
diff --git a/keystonemiddleware/tests/unit/auth_token/test_user_auth_plugin.py b/keystonemiddleware/tests/unit/auth_token/test_user_auth_plugin.py
index 8749993..554b2c3 100644
--- a/keystonemiddleware/tests/unit/auth_token/test_user_auth_plugin.py
+++ b/keystonemiddleware/tests/unit/auth_token/test_user_auth_plugin.py
@@ -80,72 +80,6 @@ class BaseUserPluginTests(object):
self.assertTokenDataEqual(service_id, service, plugin.service)
-class V2UserPluginTests(BaseUserPluginTests, base.BaseAuthTokenTestCase):
-
- def setUp(self):
- super(V2UserPluginTests, self).setUp()
-
- self.service_token = fixture.V2Token()
- self.service_token.set_scope()
- s = self.service_token.add_service('identity', name='keystone')
-
- s.add_endpoint(public=BASE_URI,
- admin=BASE_URI,
- internal=BASE_URI)
-
- self.configure_middleware(auth_type='v2password',
- auth_url='%s/v2.0/' % AUTH_URL,
- user_id=self.service_token.user_id,
- password=uuid.uuid4().hex,
- tenant_id=self.service_token.tenant_id)
-
- auth_discovery = fixture.DiscoveryList(href=AUTH_URL, v3=False)
- self.requests_mock.get(AUTH_URL, json=auth_discovery)
-
- base_discovery = fixture.DiscoveryList(href=BASE_URI, v3=False)
- self.requests_mock.get(BASE_URI, json=base_discovery)
-
- url = '%s/v2.0/tokens' % AUTH_URL
- self.requests_mock.post(url, json=self.service_token)
-
- def get_role_names(self, token):
- return [x['name'] for x in token['access']['user'].get('roles', [])]
-
- def get_token(self, service=False):
- token = fixture.V2Token()
- token.set_scope()
- token.add_role()
- if service:
- token.add_role('service')
-
- request_headers = {'X-Auth-Token': self.service_token.token_id}
-
- url = '%s/v2.0/tokens/%s' % (BASE_URI, token.token_id)
- self.requests_mock.get(url,
- request_headers=request_headers,
- json=token)
-
- return token.token_id, token
-
- def assertTokenDataEqual(self, token_id, token, token_data):
- super(V2UserPluginTests, self).assertTokenDataEqual(token_id,
- token,
- token_data)
-
- self.assertEqual(token.tenant_id, token_data.project_id)
- self.assertIsNone(token_data.user_domain_id)
- self.assertIsNone(token_data.project_domain_id)
-
- def test_trust_scope(self):
- token_id, token = self.get_token()
- token.set_trust()
-
- plugin = self.get_plugin(token_id)
- self.assertEqual(token.trust_id, plugin.user.trust_id)
- self.assertEqual(token.trustee_user_id, plugin.user.trustee_user_id)
- self.assertIsNone(plugin.user.trustor_user_id)
-
-
class V3UserPluginTests(BaseUserPluginTests, base.BaseAuthTokenTestCase):
def setUp(self):
diff --git a/keystonemiddleware/tests/unit/test_ec2_token_middleware.py b/keystonemiddleware/tests/unit/test_ec2_token_middleware.py
index 5191502..5cd69ff 100644
--- a/keystonemiddleware/tests/unit/test_ec2_token_middleware.py
+++ b/keystonemiddleware/tests/unit/test_ec2_token_middleware.py
@@ -23,13 +23,12 @@ from keystonemiddleware.tests.unit import utils
TOKEN_ID = 'fake-token-id'
-GOOD_RESPONSE = {'access': {'token': {'id': TOKEN_ID,
- 'tenant': {'id': 'TENANT_ID'}}}}
EMPTY_RESPONSE = {}
class FakeResponse(object):
reason = "Test Reason"
+ headers = {'x-subject-token': TOKEN_ID}
def __init__(self, json, status_code=400):
self._json = json
@@ -53,9 +52,9 @@ class EC2TokenMiddlewareTestBase(utils.TestCase):
TEST_PROTOCOL = 'https'
TEST_HOST = 'fakehost'
TEST_PORT = 35357
- TEST_URL = '%s://%s:%d/v2.0/ec2tokens' % (TEST_PROTOCOL,
- TEST_HOST,
- TEST_PORT)
+ TEST_URL = '%s://%s:%d/v3/ec2tokens' % (TEST_PROTOCOL,
+ TEST_HOST,
+ TEST_PORT)
def setUp(self):
super(EC2TokenMiddlewareTestBase, self).setUp()
@@ -74,7 +73,7 @@ class EC2TokenMiddlewareTestBase(utils.TestCase):
class EC2TokenMiddlewareTestGood(EC2TokenMiddlewareTestBase):
@mock.patch.object(
requests, 'request',
- return_value=FakeResponse(GOOD_RESPONSE, status_code=200))
+ return_value=FakeResponse(EMPTY_RESPONSE, status_code=200))
def test_protocol_old_versions(self, mock_request):
req = webob.Request.blank('/test')
req.GET['Signature'] = 'test-signature'
@@ -85,7 +84,7 @@ class EC2TokenMiddlewareTestGood(EC2TokenMiddlewareTestBase):
self.assertEqual(TOKEN_ID, req.headers['X-Auth-Token'])
mock_request.assert_called_with(
- 'POST', 'http://localhost:5000/v2.0/ec2tokens',
+ 'POST', 'http://localhost:5000/v3/ec2tokens',
data=mock.ANY, headers={'Content-Type': 'application/json'},
verify=True, cert=None)
@@ -105,7 +104,7 @@ class EC2TokenMiddlewareTestGood(EC2TokenMiddlewareTestBase):
@mock.patch.object(
requests, 'request',
- return_value=FakeResponse(GOOD_RESPONSE, status_code=200))
+ return_value=FakeResponse(EMPTY_RESPONSE, status_code=200))
def test_protocol_v4(self, mock_request):
req = webob.Request.blank('/test')
auth_str = (
@@ -120,7 +119,7 @@ class EC2TokenMiddlewareTestGood(EC2TokenMiddlewareTestBase):
self.assertEqual(TOKEN_ID, req.headers['X-Auth-Token'])
mock_request.assert_called_with(
- 'POST', 'http://localhost:5000/v2.0/ec2tokens',
+ 'POST', 'http://localhost:5000/v3/ec2tokens',
data=mock.ANY, headers={'Content-Type': 'application/json'},
verify=True, cert=None)
diff --git a/releasenotes/notes/ec2-v2-removal-6a886210cbc9d3e9.yaml b/releasenotes/notes/ec2-v2-removal-6a886210cbc9d3e9.yaml
new file mode 100644
index 0000000..e90fa68
--- /dev/null
+++ b/releasenotes/notes/ec2-v2-removal-6a886210cbc9d3e9.yaml
@@ -0,0 +1,7 @@
+---
+other:
+ - |
+ [`bug 1845539 <https://bugs.launchpad.net/keystone/+bug/1845539>`_]
+ The ec2 'url' config option now defaults to
+ https://localhost:5000/v3/ec2tokens with the removal of ec2 v2.0 support.
+ Keystonemiddleware no longer supports ec2tokens using the v2.0 API.
diff --git a/releasenotes/notes/removed-as-of-ussuri-4e1ea485ba8801c9.yaml b/releasenotes/notes/removed-as-of-ussuri-4e1ea485ba8801c9.yaml
new file mode 100644
index 0000000..1dafbfb
--- /dev/null
+++ b/releasenotes/notes/removed-as-of-ussuri-4e1ea485ba8801c9.yaml
@@ -0,0 +1,7 @@
+---
+upgrade:
+ - |
+ [`bug 1845539 <https://bugs.launchpad.net/keystone/+bug/1845539>`_]
+ [`bug 1777177 <https://bugs.launchpad.net/keystone/+bug/1777177>`_]
+ keystonemiddleware no longer supports the keystone v2.0 api, all
+ associated functionality has been removed.
diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst
index 62d6b53..7f0eeb6 100644
--- a/releasenotes/source/index.rst
+++ b/releasenotes/source/index.rst
@@ -6,6 +6,7 @@
:maxdepth: 1
unreleased
+ train
stein
rocky
queens
diff --git a/releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po b/releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po
index ff2a6ec..0710425 100644
--- a/releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po
+++ b/releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po
@@ -1,14 +1,15 @@
# Andi Chandler <andi@gowling.com>, 2017. #zanata
# Andi Chandler <andi@gowling.com>, 2018. #zanata
+# Andi Chandler <andi@gowling.com>, 2019. #zanata
msgid ""
msgstr ""
"Project-Id-Version: keystonemiddleware\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2018-04-21 04:01+0000\n"
+"POT-Creation-Date: 2019-12-21 02:49+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"PO-Revision-Date: 2018-04-30 10:08+0000\n"
+"PO-Revision-Date: 2019-12-21 02:38+0000\n"
"Last-Translator: Andi Chandler <andi@gowling.com>\n"
"Language-Team: English (United Kingdom)\n"
"Language: en_GB\n"
@@ -24,6 +25,9 @@ msgstr "4.12.0"
msgid "4.16.0"
msgstr "4.16.0"
+msgid "4.17.1"
+msgstr "4.17.1"
+
msgid "4.18.0"
msgstr "4.18.0"
@@ -33,6 +37,9 @@ msgstr "4.2.0"
msgid "4.20.0"
msgstr "4.20.0"
+msgid "4.22.0"
+msgstr "4.22.0"
+
msgid "4.3.0"
msgstr "4.3.0"
@@ -45,8 +52,29 @@ msgstr "4.6.0"
msgid "5.0.0"
msgstr "5.0.0"
-msgid "5.0.0-5"
-msgstr "5.0.0-5"
+msgid "5.1.0"
+msgstr "5.1.0"
+
+msgid "5.2.0"
+msgstr "5.2.0"
+
+msgid "5.2.1"
+msgstr "5.2.1"
+
+msgid "5.3.0"
+msgstr "5.3.0"
+
+msgid "6.0.0"
+msgstr "6.0.0"
+
+msgid "6.1.0"
+msgstr "6.1.0"
+
+msgid "7.0.0"
+msgstr "7.0.0"
+
+msgid "7.0.1-8"
+msgstr "7.0.1-8"
msgid ""
"A new configuration option for the s3token middleware called auth_uri can be "
@@ -135,6 +163,9 @@ msgstr "Prelude"
msgid "Queens Series Release Notes"
msgstr "Queens Series Release Notes"
+msgid "Rocky Series Release Notes"
+msgstr "Rocky Series Release Notes"
+
msgid "Security Issues"
msgstr "Security Issues"
@@ -170,6 +201,9 @@ msgstr ""
"enforce this behaviour. This will become the default setting in future "
"releases."
+msgid "Stein Series Release Notes"
+msgstr "Stein Series Release Notes"
+
msgid ""
"The ``kwargs_to_fetch_token`` setting was removed from the "
"``BaseAuthProtocol`` class. Implementations of auth_token now assume kwargs "
@@ -201,10 +235,28 @@ msgstr ""
"returned when the user needs to be redirected to the Identity service for "
"authentication."
+msgid "Train Series Release Notes"
+msgstr "Train Series Release Notes"
+
msgid "Upgrade Notes"
msgstr "Upgrade Notes"
msgid ""
+"When ``delay_auth_decision`` is enabled and a Keystone failure prevents a "
+"final decision about whether a token is valid or invalid, it will be marked "
+"invalid and the application will be responsible for a final auth decision. "
+"This is similar to what happens when a token is confirmed *not* valid. This "
+"allows a Keystone outage to only affect Keystone users in a multi-auth "
+"system."
+msgstr ""
+"When ``delay_auth_decision`` is enabled and a Keystone failure prevents a "
+"final decision about whether a token is valid or invalid, it will be marked "
+"invalid and the application will be responsible for a final auth decision. "
+"This is similar to what happens when a token is confirmed *not* valid. This "
+"allows a Keystone outage to only affect Keystone users in a multi-auth "
+"system."
+
+msgid ""
"With the release of 4.2.0 of keystonemiddleware we no longer recommend using "
"the in-process token cache. In-process caching may result in inconsistent "
"validation, poor UX and race conditions. It is recommended that the "
@@ -363,6 +415,19 @@ msgstr ""
"look for the given option in local config, then Oslo global config."
msgid ""
+"[`bug 1649735 <https://bugs.launchpad.net/keystone/+bug/1649735>`_] The "
+"auth_token middleware no longer attempts to retrieve the revocation list "
+"from the Keystone server. The deprecated options "
+"`check_revocations_for_cached` and `check_revocations_for_cached` have been "
+"removed."
+msgstr ""
+"[`bug 1649735 <https://bugs.launchpad.net/keystone/+bug/1649735>`_] The "
+"auth_token middleware no longer attempts to retrieve the revocation list "
+"from the Keystone server. The deprecated options "
+"`check_revocations_for_cached` and `check_revocations_for_cached` have been "
+"removed."
+
+msgid ""
"[`bug 1677308 <https://bugs.launchpad.net/keystonemiddleware/"
"+bug/1677308>`_] Removes ``pycrypto`` dependency as the library is "
"unmaintained, and replaces it with the ``cryptography`` library."
@@ -439,6 +504,137 @@ msgstr ""
"(Unauthorised) response now is double quoted to follow the RFC requirement."
msgid ""
+"[`bug 1766731 <https://bugs.launchpad.net/keystonemiddleware/"
+"+bug/1766731>`_] Keystonemiddleware now supports system scoped tokens. When "
+"a system-scoped token is parsed by auth_token middleware, it will set the "
+"``OpenStack-System-Scope`` header accordingly."
+msgstr ""
+"[`bug 1766731 <https://bugs.launchpad.net/keystonemiddleware/"
+"+bug/1766731>`_] Keystonemiddleware now supports system scoped tokens. When "
+"a system-scoped token is parsed by auth_token middleware, it will set the "
+"``OpenStack-System-Scope`` header accordingly."
+
+msgid ""
+"[`bug 1782404 <https://bugs.launchpad.net/keystonemiddleware/"
+"+bug/1782404>`_] Keystonemiddleware incorrectly implemented an abstraction "
+"for the memcache client pool that utilized a `queue.Queue` `get` method "
+"instead of the supplied `acquire()` context manager. The `acquire()` context "
+"manager properly places the client connection back into the pool after "
+"`__exit__`."
+msgstr ""
+"[`bug 1782404 <https://bugs.launchpad.net/keystonemiddleware/"
+"+bug/1782404>`_] Keystonemiddleware incorrectly implemented an abstraction "
+"for the memcache client pool that utilized a `queue.Queue` `get` method "
+"instead of the supplied `acquire()` context manager. The `acquire()` context "
+"manager properly places the client connection back into the pool after "
+"`__exit__`."
+
+msgid ""
+"[`bug 1789351 <https://bugs.launchpad.net/keystonemiddleware/"
+"+bug/1789351>`_] Fixed the bug that when initialize `AuthProtocol`, it'll "
+"raise \"dictionary changed size during iteration\" error if the input `CONF` "
+"object contains deprecated options."
+msgstr ""
+"[`bug 1789351 <https://bugs.launchpad.net/keystonemiddleware/"
+"+bug/1789351>`_] Fixed the bug that when initialize `AuthProtocol`, it'll "
+"raise \"dictionary changed size during iteration\" error if the input `CONF` "
+"object contains deprecated options."
+
+msgid ""
+"[`bug 1797584 <https://bugs.launchpad.net/keystonemiddleware/"
+"+bug/1797584>`_] Fixed a bug where the audit code would select the wrong "
+"target service if the OpenStack service endpoints were not using unique TCP "
+"ports."
+msgstr ""
+"[`bug 1797584 <https://bugs.launchpad.net/keystonemiddleware/"
+"+bug/1797584>`_] Fixed a bug where the audit code would select the wrong "
+"target service if the OpenStack service endpoints were not using unique TCP "
+"ports."
+
+msgid ""
+"[`bug 1800017 <https://bugs.launchpad.net/keystonemiddleware/"
+"+bug/1800017>`_] Fix audit middleware service catalog parsing for the "
+"scenario where a service does not contain any endpoints. In that case, we "
+"should just skip over that service."
+msgstr ""
+"[`bug 1800017 <https://bugs.launchpad.net/keystonemiddleware/"
+"+bug/1800017>`_] Fix audit middleware service catalog parsing for the "
+"scenario where a service does not contain any endpoints. In that case, we "
+"should just skip over that service."
+
+msgid ""
+"[`bug 1803940 <https://bugs.launchpad.net/keystonemiddleware/"
+"+bug/1803940>`_] Request ID and global request ID have been added to CADF "
+"notifications."
+msgstr ""
+"[`bug 1803940 <https://bugs.launchpad.net/keystonemiddleware/"
+"+bug/1803940>`_] Request ID and global request ID have been added to CADF "
+"notifications."
+
+msgid ""
+"[`bug 1809101 <https://bugs.launchpad.net/keystonemiddleware/"
+"+bug/1809101>`_] Fix req.context of Keystone audit middleware and Glance "
+"conflict with each other issue. The audit middleware now stores the admin "
+"context to req.environ['audit.context']."
+msgstr ""
+"[`bug 1809101 <https://bugs.launchpad.net/keystonemiddleware/"
+"+bug/1809101>`_] Fix req.context of Keystone audit middleware and Glance "
+"conflict with each other issue. The audit middleware now stores the admin "
+"context to req.environ['audit.context']."
+
+msgid ""
+"[`bug 1813739 <https://bugs.launchpad.net/keystonemiddleware/"
+"+bug/1813739>`_] When admin identity endpoint is not created yet, "
+"keystonemiddleware emit EndpointNotFound exception. Even after admin "
+"identity endpoint created, auth_token middleware could not be notified of "
+"update since it does not invalidate existing auth. Add an invalidation step "
+"so that endpoint updates can be detected."
+msgstr ""
+"[`bug 1813739 <https://bugs.launchpad.net/keystonemiddleware/"
+"+bug/1813739>`_] When admin identity endpoint is not created yet, "
+"keystonemiddleware emit EndpointNotFound exception. Even after admin "
+"identity endpoint created, auth_token middleware could not be notified of "
+"update since it does not invalidate existing auth. Add an invalidation step "
+"so that endpoint updates can be detected."
+
+msgid ""
+"[`bug 1830002 <https://bugs.launchpad.net/keystonemiddleware/"
+"+bug/1830002>`_] In order to allow an installation to work without deploying "
+"an admin Identity endpoint, a new option `interface` has been added, "
+"allowing select the Identity endpoint that is being used when verifying auth "
+"tokens. It defaults to `admin` in order to replicate the old behaviour, but "
+"may be set to `public` or `internal` as needed."
+msgstr ""
+"[`bug 1830002 <https://bugs.launchpad.net/keystonemiddleware/"
+"+bug/1830002>`_] In order to allow an installation to work without deploying "
+"an admin Identity endpoint, a new option `interface` has been added, "
+"allowing select the Identity endpoint that is being used when verifying auth "
+"tokens. It defaults to `admin` in order to replicate the old behaviour, but "
+"may be set to `public` or `internal` as needed."
+
+msgid ""
+"[`bug 1845539 <https://bugs.launchpad.net/keystone/+bug/1845539>`_] The ec2 "
+"'url' config option now defaults to https://localhost:5000/v3/ec2tokens with "
+"the removal of ec2 v2.0 support. Keystonemiddleware no longer supports "
+"ec2tokens using the v2.0 API."
+msgstr ""
+"[`bug 1845539 <https://bugs.launchpad.net/keystone/+bug/1845539>`_] The ec2 "
+"'url' config option now defaults to https://localhost:5000/v3/ec2tokens with "
+"the removal of ec2 v2.0 support. Keystonemiddleware no longer supports "
+"ec2tokens using the v2.0 API."
+
+msgid ""
+"[`bug 1845539 <https://bugs.launchpad.net/keystone/+bug/1845539>`_] [`bug "
+"1777177 <https://bugs.launchpad.net/keystone/+bug/1777177>`_] "
+"keystonemiddleware no longer supports the keystone v2.0 api, all associated "
+"functionality has been removed."
+msgstr ""
+"[`bug 1845539 <https://bugs.launchpad.net/keystone/+bug/1845539>`_] [`bug "
+"1777177 <https://bugs.launchpad.net/keystone/+bug/1777177>`_] "
+"keystonemiddleware no longer supports the Keystone v2.0 api, all associated "
+"functionality has been removed."
+
+msgid ""
"[`bug/1747655 <https://bugs.launchpad.net/keystonemiddleware/"
"+bug/1747655>`_] When keystone is temporarily unavailable, "
"keystonemiddleware correctly sends a 503 response to the HTTP client but was "
@@ -453,5 +649,16 @@ msgstr ""
"was keystone or the service using keystonemiddleware that was unavailable. "
"This change identifies keystone in the error response."
+msgid ""
+"[`spec <http://specs.openstack.org/openstack/keystone-specs/specs/keystone/"
+"train/capabilities-app-creds.html>`_] The auth_token middleware now has "
+"support for accepting or denying incoming requests based on access rules "
+"provided by users in their keystone application credentials."
+msgstr ""
+"[`spec <http://specs.openstack.org/openstack/keystone-specs/specs/keystone/"
+"train/capabilities-app-creds.html>`_] The auth_token middleware now has "
+"support for accepting or denying incoming requests based on access rules "
+"provided by users in their Keystone application credentials."
+
msgid "keystonemiddleware Release Notes"
msgstr "keystonemiddleware Release Notes"
diff --git a/releasenotes/source/train.rst b/releasenotes/source/train.rst
new file mode 100644
index 0000000..5839003
--- /dev/null
+++ b/releasenotes/source/train.rst
@@ -0,0 +1,6 @@
+==========================
+Train Series Release Notes
+==========================
+
+.. release-notes::
+ :branch: stable/train
diff --git a/tox.ini b/tox.ini
index 5468d4f..432b8fa 100644
--- a/tox.ini
+++ b/tox.ini
@@ -64,6 +64,18 @@ commands=
doc8 doc/source
sphinx-build -W -b html doc/source doc/build/html
+[testenv:pdf-docs]
+basepython = python3
+envdir = {toxworkdir}/docs
+deps = {[testenv:docs]deps}
+whitelist_externals =
+ make
+ rm
+commands =
+ rm -rf doc/build/pdf
+ sphinx-build -W -b latex doc/source doc/build/pdf
+ make -C doc/build/pdf
+
[testenv:releasenotes]
basepython = python3
deps = -r{toxinidir}/doc/requirements.txt