I18n
The strings weren't marked for translation. DocImpact implements bp keystonemiddleware-i18n Change-Id: Ic7da29b54b1547ff8df002bd77f61f2ebff35217
This commit is contained in:
parent
70f9d05eaf
commit
273539bf26
@ -36,6 +36,8 @@ import os
|
|||||||
import six
|
import six
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
from keystonemiddleware.i18n import _
|
||||||
|
|
||||||
# make sure pycrypto is available
|
# make sure pycrypto is available
|
||||||
try:
|
try:
|
||||||
from Crypto.Cipher import AES
|
from Crypto.Cipher import AES
|
||||||
@ -150,7 +152,7 @@ def decrypt_data(key, data):
|
|||||||
try:
|
try:
|
||||||
result = cipher.decrypt(data[16:])
|
result = cipher.decrypt(data[16:])
|
||||||
except Exception:
|
except Exception:
|
||||||
raise DecryptError('Encrypted data appears to be corrupted.')
|
raise DecryptError(_('Encrypted data appears to be corrupted.'))
|
||||||
|
|
||||||
# Strip the last n padding bytes where n is the last value in
|
# Strip the last n padding bytes where n is the last value in
|
||||||
# the plaintext
|
# the plaintext
|
||||||
@ -189,7 +191,7 @@ def unprotect_data(keys, signed_data):
|
|||||||
|
|
||||||
# Then verify that it matches the provided value
|
# Then verify that it matches the provided value
|
||||||
if not constant_time_compare(provided_mac, calculated_mac):
|
if not constant_time_compare(provided_mac, calculated_mac):
|
||||||
raise InvalidMacError('Invalid MAC; data appears to be corrupted.')
|
raise InvalidMacError(_('Invalid MAC; data appears to be corrupted.'))
|
||||||
|
|
||||||
data = base64.b64decode(signed_data[DIGEST_LENGTH_B64:])
|
data = base64.b64decode(signed_data[DIGEST_LENGTH_B64:])
|
||||||
|
|
||||||
|
@ -26,6 +26,8 @@ import time
|
|||||||
|
|
||||||
from six.moves import queue
|
from six.moves import queue
|
||||||
|
|
||||||
|
from keystonemiddleware.i18n import _LC
|
||||||
|
|
||||||
|
|
||||||
_PoolItem = collections.namedtuple('_PoolItem', ['ttl', 'connection'])
|
_PoolItem = collections.namedtuple('_PoolItem', ['ttl', 'connection'])
|
||||||
|
|
||||||
@ -74,8 +76,8 @@ class ConnectionPool(queue.Queue):
|
|||||||
try:
|
try:
|
||||||
conn = self.get(timeout=self._connection_get_timeout)
|
conn = self.get(timeout=self._connection_get_timeout)
|
||||||
except queue.Empty:
|
except queue.Empty:
|
||||||
self._LOG.critical('Unable to get a connection from pool id '
|
self._LOG.critical(_LC('Unable to get a connection from pool id '
|
||||||
'%(id)s after %(seconds)s seconds.',
|
'%(id)s after %(seconds)s seconds.'),
|
||||||
{'id': id(self),
|
{'id': id(self),
|
||||||
'seconds': self._connection_get_timeout})
|
'seconds': self._connection_get_timeout})
|
||||||
raise ConnectionGetTimeoutException()
|
raise ConnectionGetTimeoutException()
|
||||||
|
@ -183,6 +183,7 @@ import six
|
|||||||
from six.moves import urllib
|
from six.moves import urllib
|
||||||
|
|
||||||
from keystonemiddleware import _memcache_crypt as memcache_crypt
|
from keystonemiddleware import _memcache_crypt as memcache_crypt
|
||||||
|
from keystonemiddleware.i18n import _, _LE, _LI, _LW
|
||||||
from keystonemiddleware.openstack.common import memorycache
|
from keystonemiddleware.openstack.common import memorycache
|
||||||
|
|
||||||
|
|
||||||
@ -393,13 +394,13 @@ def _token_is_v3(token_info):
|
|||||||
|
|
||||||
def _get_token_expiration(data):
|
def _get_token_expiration(data):
|
||||||
if not data:
|
if not data:
|
||||||
raise InvalidToken('Token authorization failed')
|
raise InvalidToken(_('Token authorization failed'))
|
||||||
if _token_is_v2(data):
|
if _token_is_v2(data):
|
||||||
timestamp = data['access']['token']['expires']
|
timestamp = data['access']['token']['expires']
|
||||||
elif _token_is_v3(data):
|
elif _token_is_v3(data):
|
||||||
timestamp = data['token']['expires_at']
|
timestamp = data['token']['expires_at']
|
||||||
else:
|
else:
|
||||||
raise InvalidToken('Token authorization failed')
|
raise InvalidToken(_('Token authorization failed'))
|
||||||
expires = timeutils.parse_isotime(timestamp)
|
expires = timeutils.parse_isotime(timestamp)
|
||||||
expires = timeutils.normalize_time(expires)
|
expires = timeutils.normalize_time(expires)
|
||||||
return expires
|
return expires
|
||||||
@ -409,7 +410,7 @@ def _confirm_token_not_expired(data):
|
|||||||
expires = _get_token_expiration(data)
|
expires = _get_token_expiration(data)
|
||||||
utcnow = timeutils.utcnow()
|
utcnow = timeutils.utcnow()
|
||||||
if utcnow >= expires:
|
if utcnow >= expires:
|
||||||
raise InvalidToken('Token authorization failed')
|
raise InvalidToken(_('Token authorization failed'))
|
||||||
return timeutils.isotime(at=expires, subsecond=True)
|
return timeutils.isotime(at=expires, subsecond=True)
|
||||||
|
|
||||||
|
|
||||||
@ -470,8 +471,8 @@ def _conf_values_type_convert(conf):
|
|||||||
opts[k] = v
|
opts[k] = v
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
raise ConfigurationError(
|
raise ConfigurationError(
|
||||||
'Unable to convert the value of %s option into correct '
|
_('Unable to convert the value of %(key)s option into correct '
|
||||||
'type: %s' % (k, e))
|
'type: %(ex)s') % {'key': k, 'ex': e})
|
||||||
return opts
|
return opts
|
||||||
|
|
||||||
|
|
||||||
@ -509,9 +510,9 @@ class _AuthTokenPlugin(auth.BaseAuthPlugin):
|
|||||||
# are backwards. We need to do it this way so that we can handle the
|
# are backwards. We need to do it this way so that we can handle the
|
||||||
# same deprecation strategy for CONF and the conf variable.
|
# same deprecation strategy for CONF and the conf variable.
|
||||||
if not identity_uri:
|
if not identity_uri:
|
||||||
log.warning('Configuring admin URI using auth fragments. '
|
log.warning(_LW('Configuring admin URI using auth fragments. '
|
||||||
'This is deprecated, use \'identity_uri\''
|
'This is deprecated, use \'identity_uri\''
|
||||||
' instead.')
|
' instead.'))
|
||||||
|
|
||||||
if ':' in auth_host:
|
if ':' in auth_host:
|
||||||
# Note(dzyu) it is an IPv6 address, so it needs to be wrapped
|
# Note(dzyu) it is an IPv6 address, so it needs to be wrapped
|
||||||
@ -536,11 +537,11 @@ class _AuthTokenPlugin(auth.BaseAuthPlugin):
|
|||||||
auth_url = '%s/v2.0' % self._identity_uri
|
auth_url = '%s/v2.0' % self._identity_uri
|
||||||
|
|
||||||
if admin_token:
|
if admin_token:
|
||||||
log.warning(
|
log.warning(_LW(
|
||||||
"The admin_token option in the auth_token middleware is "
|
"The admin_token option in the auth_token middleware is "
|
||||||
"deprecated and should not be used. The admin_user and "
|
"deprecated and should not be used. The admin_user and "
|
||||||
"admin_password options should be used instead. The "
|
"admin_password options should be used instead. The "
|
||||||
"admin_token option may be removed in a future release.")
|
"admin_token option may be removed in a future release."))
|
||||||
self._plugin = token_endpoint.Token(auth_url, admin_token)
|
self._plugin = token_endpoint.Token(auth_url, admin_token)
|
||||||
else:
|
else:
|
||||||
self._plugin = v2.Password(auth_url,
|
self._plugin = v2.Password(auth_url,
|
||||||
@ -660,7 +661,7 @@ class AuthProtocol(object):
|
|||||||
|
|
||||||
def __init__(self, app, conf):
|
def __init__(self, app, conf):
|
||||||
self._LOG = logging.getLogger(conf.get('log_name', __name__))
|
self._LOG = logging.getLogger(conf.get('log_name', __name__))
|
||||||
self._LOG.info('Starting keystone auth_token middleware')
|
self._LOG.info(_LI('Starting keystone auth_token middleware'))
|
||||||
# NOTE(wanghong): If options are set in paste file, all the option
|
# NOTE(wanghong): If options are set in paste file, all the option
|
||||||
# values passed into conf are string type. So, we should convert the
|
# values passed into conf are string type. So, we should convert the
|
||||||
# conf value into correct type.
|
# conf value into correct type.
|
||||||
@ -683,8 +684,9 @@ class AuthProtocol(object):
|
|||||||
if self._signing_dirname is None:
|
if self._signing_dirname is None:
|
||||||
self._signing_dirname = tempfile.mkdtemp(
|
self._signing_dirname = tempfile.mkdtemp(
|
||||||
prefix='keystone-signing-')
|
prefix='keystone-signing-')
|
||||||
self._LOG.info('Using %s as cache directory for signing certificate',
|
self._LOG.info(
|
||||||
self._signing_dirname)
|
_LI('Using %s as cache directory for signing certificate'),
|
||||||
|
self._signing_dirname)
|
||||||
self._verify_signing_dir()
|
self._verify_signing_dir()
|
||||||
|
|
||||||
val = '%s/signing_cert.pem' % self._signing_dirname
|
val = '%s/signing_cert.pem' % self._signing_dirname
|
||||||
@ -757,10 +759,12 @@ class AuthProtocol(object):
|
|||||||
except InvalidToken:
|
except InvalidToken:
|
||||||
if self._delay_auth_decision:
|
if self._delay_auth_decision:
|
||||||
self._LOG.info(
|
self._LOG.info(
|
||||||
'Invalid user token - deferring reject downstream')
|
_LI('Invalid user token - deferring reject '
|
||||||
|
'downstream'))
|
||||||
self._add_headers(env, {'X-Identity-Status': 'Invalid'})
|
self._add_headers(env, {'X-Identity-Status': 'Invalid'})
|
||||||
else:
|
else:
|
||||||
self._LOG.info('Invalid user token - rejecting request')
|
self._LOG.info(
|
||||||
|
_LI('Invalid user token - rejecting request'))
|
||||||
return self._reject_request(env, start_response)
|
return self._reject_request(env, start_response)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -774,11 +778,12 @@ class AuthProtocol(object):
|
|||||||
except InvalidToken:
|
except InvalidToken:
|
||||||
# Delayed auth not currently supported for service tokens.
|
# Delayed auth not currently supported for service tokens.
|
||||||
# (Can be implemented if a use case is found.)
|
# (Can be implemented if a use case is found.)
|
||||||
self._LOG.info('Invalid service token - rejecting request')
|
self._LOG.info(
|
||||||
|
_LI('Invalid service token - rejecting request'))
|
||||||
return self._reject_request(env, start_response)
|
return self._reject_request(env, start_response)
|
||||||
|
|
||||||
except ServiceError as e:
|
except ServiceError as e:
|
||||||
self._LOG.critical('Unable to obtain admin token: %s', e)
|
self._LOG.critical(_LC('Unable to obtain admin token: %s'), e)
|
||||||
resp = _MiniResp('Service unavailable', env)
|
resp = _MiniResp('Service unavailable', env)
|
||||||
start_response('503 Service Unavailable', resp.headers)
|
start_response('503 Service Unavailable', resp.headers)
|
||||||
return resp.body
|
return resp.body
|
||||||
@ -834,10 +839,10 @@ class AuthProtocol(object):
|
|||||||
return token
|
return token
|
||||||
else:
|
else:
|
||||||
if not self._delay_auth_decision:
|
if not self._delay_auth_decision:
|
||||||
self._LOG.warn('Unable to find authentication token'
|
self._LOG.warn(_LW('Unable to find authentication token'
|
||||||
' in headers')
|
' in headers'))
|
||||||
self._LOG.debug('Headers: %s', env)
|
self._LOG.debug('Headers: %s', env)
|
||||||
raise InvalidToken('Unable to find token in headers')
|
raise InvalidToken(_('Unable to find token in headers'))
|
||||||
|
|
||||||
def _get_service_token_from_header(self, env):
|
def _get_service_token_from_header(self, env):
|
||||||
"""Get service token id from request.
|
"""Get service token id from request.
|
||||||
@ -899,7 +904,7 @@ class AuthProtocol(object):
|
|||||||
self._LOG.debug(
|
self._LOG.debug(
|
||||||
'Token is marked as having been revoked')
|
'Token is marked as having been revoked')
|
||||||
raise InvalidToken(
|
raise InvalidToken(
|
||||||
'Token authorization failed')
|
_('Token authorization failed'))
|
||||||
self._confirm_token_bind(data, env)
|
self._confirm_token_bind(data, env)
|
||||||
else:
|
else:
|
||||||
# Token wasn't cached. In this case, the token needs to be
|
# Token wasn't cached. In this case, the token needs to be
|
||||||
@ -923,14 +928,14 @@ class AuthProtocol(object):
|
|||||||
return data
|
return data
|
||||||
except (exceptions.ConnectionRefused, exceptions.RequestTimeout):
|
except (exceptions.ConnectionRefused, exceptions.RequestTimeout):
|
||||||
self._LOG.debug('Token validation failure.', exc_info=True)
|
self._LOG.debug('Token validation failure.', exc_info=True)
|
||||||
self._LOG.warn('Authorization failed for token')
|
self._LOG.warn(_LW('Authorization failed for token'))
|
||||||
raise InvalidToken('Token authorization failed')
|
raise InvalidToken(_('Token authorization failed'))
|
||||||
except Exception:
|
except Exception:
|
||||||
self._LOG.debug('Token validation failure.', exc_info=True)
|
self._LOG.debug('Token validation failure.', exc_info=True)
|
||||||
if token_id:
|
if token_id:
|
||||||
self._token_cache.store_invalid(token_id)
|
self._token_cache.store_invalid(token_id)
|
||||||
self._LOG.warn('Authorization failed for token')
|
self._LOG.warn(_LW('Authorization failed for token'))
|
||||||
raise InvalidToken('Token authorization failed')
|
raise InvalidToken(_('Token authorization failed'))
|
||||||
|
|
||||||
def _build_user_headers(self, auth_ref, token_info):
|
def _build_user_headers(self, auth_ref, token_info):
|
||||||
"""Convert token object into headers.
|
"""Convert token object into headers.
|
||||||
@ -946,7 +951,7 @@ class AuthProtocol(object):
|
|||||||
roles = ','.join(auth_ref.role_names)
|
roles = ','.join(auth_ref.role_names)
|
||||||
|
|
||||||
if _token_is_v2(token_info) and not auth_ref.project_id:
|
if _token_is_v2(token_info) and not auth_ref.project_id:
|
||||||
raise InvalidToken('Unable to determine tenancy.')
|
raise InvalidToken(_('Unable to determine tenancy.'))
|
||||||
|
|
||||||
rval = {
|
rval = {
|
||||||
'X-Identity-Status': 'Confirmed',
|
'X-Identity-Status': 'Confirmed',
|
||||||
@ -983,7 +988,7 @@ class AuthProtocol(object):
|
|||||||
auth_ref = access.AccessInfo.factory(body=token_info)
|
auth_ref = access.AccessInfo.factory(body=token_info)
|
||||||
|
|
||||||
if _token_is_v2(token_info) and not auth_ref.project_id:
|
if _token_is_v2(token_info) and not auth_ref.project_id:
|
||||||
raise InvalidToken('Unable to determine service tenancy.')
|
raise InvalidToken(_('Unable to determine service tenancy.'))
|
||||||
|
|
||||||
roles = ','.join(auth_ref.role_names)
|
roles = ','.join(auth_ref.role_names)
|
||||||
rval = {
|
rval = {
|
||||||
@ -1028,7 +1033,7 @@ class AuthProtocol(object):
|
|||||||
def _invalid_user_token(self, msg=False):
|
def _invalid_user_token(self, msg=False):
|
||||||
# NOTE(jamielennox): use False as the default so that None is valid
|
# NOTE(jamielennox): use False as the default so that None is valid
|
||||||
if msg is False:
|
if msg is False:
|
||||||
msg = 'Token authorization failed'
|
msg = _('Token authorization failed')
|
||||||
|
|
||||||
raise InvalidToken(msg)
|
raise InvalidToken(msg)
|
||||||
|
|
||||||
@ -1056,7 +1061,7 @@ class AuthProtocol(object):
|
|||||||
# no bind provided and none required
|
# no bind provided and none required
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
self._LOG.info('No bind information present in token.')
|
self._LOG.info(_LI('No bind information present in token.'))
|
||||||
self._invalid_user_token()
|
self._invalid_user_token()
|
||||||
|
|
||||||
# get the named mode if bind_mode is not one of the predefined
|
# get the named mode if bind_mode is not one of the predefined
|
||||||
@ -1066,19 +1071,20 @@ class AuthProtocol(object):
|
|||||||
name = bind_mode
|
name = bind_mode
|
||||||
|
|
||||||
if name and name not in bind:
|
if name and name not in bind:
|
||||||
self._LOG.info('Named bind mode %s not in bind information', name)
|
self._LOG.info(_LI('Named bind mode %s not in bind information'),
|
||||||
|
name)
|
||||||
self._invalid_user_token()
|
self._invalid_user_token()
|
||||||
|
|
||||||
for bind_type, identifier in six.iteritems(bind):
|
for bind_type, identifier in six.iteritems(bind):
|
||||||
if bind_type == _BIND_MODE.KERBEROS:
|
if bind_type == _BIND_MODE.KERBEROS:
|
||||||
if not env.get('AUTH_TYPE', '').lower() == 'negotiate':
|
if not env.get('AUTH_TYPE', '').lower() == 'negotiate':
|
||||||
self._LOG.info('Kerberos credentials required and '
|
self._LOG.info(_LI('Kerberos credentials required and '
|
||||||
'not present.')
|
'not present.'))
|
||||||
self._invalid_user_token()
|
self._invalid_user_token()
|
||||||
|
|
||||||
if not env.get('REMOTE_USER') == identifier:
|
if not env.get('REMOTE_USER') == identifier:
|
||||||
self._LOG.info('Kerberos credentials do not match '
|
self._LOG.info(_LI('Kerberos credentials do not match '
|
||||||
'those in bind.')
|
'those in bind.'))
|
||||||
self._invalid_user_token()
|
self._invalid_user_token()
|
||||||
|
|
||||||
self._LOG.debug('Kerberos bind authentication successful.')
|
self._LOG.debug('Kerberos bind authentication successful.')
|
||||||
@ -1090,10 +1096,10 @@ class AuthProtocol(object):
|
|||||||
'identifier': identifier})
|
'identifier': identifier})
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self._LOG.info('Couldn`t verify unknown bind: %(bind_type)s: '
|
self._LOG.info(
|
||||||
'%(identifier)s.',
|
_LI('Couldn`t verify unknown bind: %(bind_type)s: '
|
||||||
{'bind_type': bind_type,
|
'%(identifier)s.'),
|
||||||
'identifier': identifier})
|
{'bind_type': bind_type, 'identifier': identifier})
|
||||||
self._invalid_user_token()
|
self._invalid_user_token()
|
||||||
|
|
||||||
def _is_signed_token_revoked(self, token_ids):
|
def _is_signed_token_revoked(self, token_ids):
|
||||||
@ -1126,7 +1132,7 @@ class AuthProtocol(object):
|
|||||||
self._signing_ca_file_name,
|
self._signing_ca_file_name,
|
||||||
inform=inform).decode('utf-8')
|
inform=inform).decode('utf-8')
|
||||||
except cms.subprocess.CalledProcessError as err:
|
except cms.subprocess.CalledProcessError as err:
|
||||||
self._LOG.warning('Verify error: %s', err)
|
self._LOG.warning(_LW('Verify error: %s'), err)
|
||||||
raise
|
raise
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -1142,13 +1148,13 @@ class AuthProtocol(object):
|
|||||||
except exceptions.CertificateConfigError as err:
|
except exceptions.CertificateConfigError as err:
|
||||||
# if this is still occurring, something else is wrong and we
|
# if this is still occurring, something else is wrong and we
|
||||||
# need err.output to identify the problem
|
# need err.output to identify the problem
|
||||||
self._LOG.error('CMS Verify output: %s', err.output)
|
self._LOG.error(_LE('CMS Verify output: %s'), err.output)
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def _verify_signed_token(self, signed_text, token_ids):
|
def _verify_signed_token(self, signed_text, token_ids):
|
||||||
"""Check that the token is unrevoked and has a valid signature."""
|
"""Check that the token is unrevoked and has a valid signature."""
|
||||||
if self._is_signed_token_revoked(token_ids):
|
if self._is_signed_token_revoked(token_ids):
|
||||||
raise InvalidToken('Token has been revoked')
|
raise InvalidToken(_('Token has been revoked'))
|
||||||
|
|
||||||
formatted = cms.token_to_cms(signed_text)
|
formatted = cms.token_to_cms(signed_text)
|
||||||
verified = self._cms_verify(formatted)
|
verified = self._cms_verify(formatted)
|
||||||
@ -1156,7 +1162,7 @@ class AuthProtocol(object):
|
|||||||
|
|
||||||
def _verify_pkiz_token(self, signed_text, token_ids):
|
def _verify_pkiz_token(self, signed_text, token_ids):
|
||||||
if self._is_signed_token_revoked(token_ids):
|
if self._is_signed_token_revoked(token_ids):
|
||||||
raise InvalidToken('Token has been revoked')
|
raise InvalidToken(_('Token has been revoked'))
|
||||||
try:
|
try:
|
||||||
uncompressed = cms.pkiz_uncompress(signed_text)
|
uncompressed = cms.pkiz_uncompress(signed_text)
|
||||||
verified = self._cms_verify(uncompressed, inform=cms.PKIZ_CMS_FORM)
|
verified = self._cms_verify(uncompressed, inform=cms.PKIZ_CMS_FORM)
|
||||||
@ -1169,14 +1175,15 @@ class AuthProtocol(object):
|
|||||||
if os.path.exists(self._signing_dirname):
|
if os.path.exists(self._signing_dirname):
|
||||||
if not os.access(self._signing_dirname, os.W_OK):
|
if not os.access(self._signing_dirname, os.W_OK):
|
||||||
raise ConfigurationError(
|
raise ConfigurationError(
|
||||||
'unable to access signing_dir %s' % self._signing_dirname)
|
_('unable to access signing_dir %s') %
|
||||||
|
self._signing_dirname)
|
||||||
uid = os.getuid()
|
uid = os.getuid()
|
||||||
if os.stat(self._signing_dirname).st_uid != uid:
|
if os.stat(self._signing_dirname).st_uid != uid:
|
||||||
self._LOG.warning('signing_dir is not owned by %s', uid)
|
self._LOG.warning(_LW('signing_dir is not owned by %s'), uid)
|
||||||
current_mode = stat.S_IMODE(os.stat(self._signing_dirname).st_mode)
|
current_mode = stat.S_IMODE(os.stat(self._signing_dirname).st_mode)
|
||||||
if current_mode != stat.S_IRWXU:
|
if current_mode != stat.S_IRWXU:
|
||||||
self._LOG.warning(
|
self._LOG.warning(
|
||||||
'signing_dir mode is %s instead of %s',
|
_LW('signing_dir mode is %s instead of %s'),
|
||||||
oct(current_mode), oct(stat.S_IRWXU))
|
oct(current_mode), oct(stat.S_IRWXU))
|
||||||
else:
|
else:
|
||||||
os.makedirs(self._signing_dirname, stat.S_IRWXU)
|
os.makedirs(self._signing_dirname, stat.S_IRWXU)
|
||||||
@ -1404,9 +1411,9 @@ class _IdentityServer(object):
|
|||||||
|
|
||||||
if auth_uri is None:
|
if auth_uri is None:
|
||||||
self._LOG.warning(
|
self._LOG.warning(
|
||||||
'Configuring auth_uri to point to the public identity '
|
_LW('Configuring auth_uri to point to the public identity '
|
||||||
'endpoint is required; clients may not be able to '
|
'endpoint is required; clients may not be able to '
|
||||||
'authenticate against an admin endpoint')
|
'authenticate against an admin endpoint'))
|
||||||
|
|
||||||
# FIXME(dolph): drop support for this fallback behavior as
|
# FIXME(dolph): drop support for this fallback behavior as
|
||||||
# documented in bug 1207517.
|
# documented in bug 1207517.
|
||||||
@ -1461,18 +1468,19 @@ class _IdentityServer(object):
|
|||||||
endpoint_filter={'version': version},
|
endpoint_filter={'version': version},
|
||||||
headers=headers)
|
headers=headers)
|
||||||
except exceptions.NotFound as e:
|
except exceptions.NotFound as e:
|
||||||
self._LOG.warn('Authorization failed for token')
|
self._LOG.warn(_LW('Authorization failed for token'))
|
||||||
self._LOG.warn('Identity response: %s' % e.response.text)
|
self._LOG.warn(_LW('Identity response: %s') % e.response.text)
|
||||||
except exceptions.Unauthorized as e:
|
except exceptions.Unauthorized as e:
|
||||||
self._LOG.info('Keystone rejected authorization')
|
self._LOG.info(_LI('Keystone rejected authorization'))
|
||||||
self._LOG.warn('Identity response: %s' % e.response.text)
|
self._LOG.warn(_LW('Identity response: %s') % e.response.text)
|
||||||
if retry:
|
if retry:
|
||||||
self._LOG.info('Retrying validation')
|
self._LOG.info(_LI('Retrying validation'))
|
||||||
return self.verify_token(user_token, False)
|
return self.verify_token(user_token, False)
|
||||||
except exceptions.HttpError as e:
|
except exceptions.HttpError as e:
|
||||||
self._LOG.error('Bad response code while validating token: %s',
|
self._LOG.error(
|
||||||
e.http_status)
|
_LE('Bad response code while validating token: %s'),
|
||||||
self._LOG.warn('Identity response: %s' % e.response.text)
|
e.http_status)
|
||||||
|
self._LOG.warn(_LW('Identity response: %s') % e.response.text)
|
||||||
else:
|
else:
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
return data
|
return data
|
||||||
@ -1486,12 +1494,12 @@ class _IdentityServer(object):
|
|||||||
authenticated=True,
|
authenticated=True,
|
||||||
endpoint_filter={'version': (2, 0)})
|
endpoint_filter={'version': (2, 0)})
|
||||||
except exceptions.HTTPError as e:
|
except exceptions.HTTPError as e:
|
||||||
raise ServiceError('Failed to fetch token revocation list: %d' %
|
raise ServiceError(_('Failed to fetch token revocation list: %d') %
|
||||||
e.http_status)
|
e.http_status)
|
||||||
if response.status_code != 200:
|
if response.status_code != 200:
|
||||||
raise ServiceError('Unable to fetch token revocation list.')
|
raise ServiceError(_('Unable to fetch token revocation list.'))
|
||||||
if 'signed' not in data:
|
if 'signed' not in data:
|
||||||
raise ServiceError('Revocation list improperly formatted.')
|
raise ServiceError(_('Revocation list improperly formatted.'))
|
||||||
return data['signed']
|
return data['signed']
|
||||||
|
|
||||||
def fetch_signing_cert(self):
|
def fetch_signing_cert(self):
|
||||||
@ -1511,7 +1519,7 @@ class _IdentityServer(object):
|
|||||||
# server.
|
# server.
|
||||||
if self._req_auth_version:
|
if self._req_auth_version:
|
||||||
version_to_use = self._req_auth_version
|
version_to_use = self._req_auth_version
|
||||||
self._LOG.info('Auth Token proceeding with requested %s apis',
|
self._LOG.info(_LI('Auth Token proceeding with requested %s apis'),
|
||||||
version_to_use)
|
version_to_use)
|
||||||
else:
|
else:
|
||||||
version_to_use = None
|
version_to_use = None
|
||||||
@ -1522,15 +1530,15 @@ class _IdentityServer(object):
|
|||||||
version_to_use = version
|
version_to_use = version
|
||||||
break
|
break
|
||||||
if version_to_use:
|
if version_to_use:
|
||||||
self._LOG.info('Auth Token confirmed use of %s apis',
|
self._LOG.info(_LI('Auth Token confirmed use of %s apis'),
|
||||||
version_to_use)
|
version_to_use)
|
||||||
else:
|
else:
|
||||||
self._LOG.error(
|
self._LOG.error(
|
||||||
'Attempted versions [%s] not in list supported by '
|
_LE('Attempted versions [%(attempt)s] not in list '
|
||||||
'server [%s]',
|
'supported by server [%(supported)s]'),
|
||||||
', '.join(_LIST_OF_VERSIONS_TO_ATTEMPT),
|
{'attempt': ', '.join(_LIST_OF_VERSIONS_TO_ATTEMPT),
|
||||||
', '.join(versions_supported_by_server))
|
'supported': ', '.join(versions_supported_by_server)})
|
||||||
raise ServiceError('No compatible apis supported by server')
|
raise ServiceError(_('No compatible apis supported by server'))
|
||||||
return version_to_use
|
return version_to_use
|
||||||
|
|
||||||
def _get_supported_versions(self):
|
def _get_supported_versions(self):
|
||||||
@ -1541,21 +1549,22 @@ class _IdentityServer(object):
|
|||||||
endpoint_filter={'interface': auth.AUTH_INTERFACE})
|
endpoint_filter={'interface': auth.AUTH_INTERFACE})
|
||||||
if response.status_code == 501:
|
if response.status_code == 501:
|
||||||
self._LOG.warning(
|
self._LOG.warning(
|
||||||
'Old keystone installation found...assuming v2.0')
|
_LW('Old keystone installation found...assuming v2.0'))
|
||||||
versions.append('v2.0')
|
versions.append('v2.0')
|
||||||
elif response.status_code != 300:
|
elif response.status_code != 300:
|
||||||
self._LOG.error('Unable to get version info from keystone: %s',
|
self._LOG.error(
|
||||||
response.status_code)
|
_LE('Unable to get version info from keystone: %s'),
|
||||||
raise ServiceError('Unable to get version info from keystone')
|
response.status_code)
|
||||||
|
raise ServiceError(_('Unable to get version info from keystone'))
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
for version in data['versions']['values']:
|
for version in data['versions']['values']:
|
||||||
versions.append(version['id'])
|
versions.append(version['id'])
|
||||||
except KeyError:
|
except KeyError:
|
||||||
self._LOG.error(
|
self._LOG.error(
|
||||||
'Invalid version response format from server')
|
_LE('Invalid version response format from server'))
|
||||||
raise ServiceError('Unable to parse version response '
|
raise ServiceError(_('Unable to parse version response '
|
||||||
'from keystone')
|
'from keystone'))
|
||||||
|
|
||||||
self._LOG.debug('Server reports support for api versions: %s',
|
self._LOG.debug('Server reports support for api versions: %s',
|
||||||
', '.join(versions))
|
', '.join(versions))
|
||||||
@ -1810,7 +1819,7 @@ class _TokenCache(object):
|
|||||||
cached = jsonutils.loads(data)
|
cached = jsonutils.loads(data)
|
||||||
if cached == self._INVALID_INDICATOR:
|
if cached == self._INVALID_INDICATOR:
|
||||||
self._LOG.debug('Cached Token is marked unauthorized')
|
self._LOG.debug('Cached Token is marked unauthorized')
|
||||||
raise InvalidToken('Token authorization failed')
|
raise InvalidToken(_('Token authorization failed'))
|
||||||
|
|
||||||
data, expires = cached
|
data, expires = cached
|
||||||
|
|
||||||
@ -1829,7 +1838,7 @@ class _TokenCache(object):
|
|||||||
return data
|
return data
|
||||||
else:
|
else:
|
||||||
self._LOG.debug('Cached Token seems expired')
|
self._LOG.debug('Cached Token seems expired')
|
||||||
raise InvalidToken('Token authorization failed')
|
raise InvalidToken(_('Token authorization failed'))
|
||||||
|
|
||||||
def _cache_store(self, token_id, data):
|
def _cache_store(self, token_id, data):
|
||||||
"""Store value into memcache.
|
"""Store value into memcache.
|
||||||
@ -1861,12 +1870,12 @@ class _SecureTokenCache(_TokenCache):
|
|||||||
security_strategy = security_strategy.upper()
|
security_strategy = security_strategy.upper()
|
||||||
|
|
||||||
if security_strategy not in ('MAC', 'ENCRYPT'):
|
if security_strategy not in ('MAC', 'ENCRYPT'):
|
||||||
raise ConfigurationError('memcache_security_strategy must be '
|
raise ConfigurationError(_('memcache_security_strategy must be '
|
||||||
'ENCRYPT or MAC')
|
'ENCRYPT or MAC'))
|
||||||
if not secret_key:
|
if not secret_key:
|
||||||
raise ConfigurationError('memcache_secret_key must be defined '
|
raise ConfigurationError(_('memcache_secret_key must be defined '
|
||||||
'when a memcache_security_strategy '
|
'when a memcache_security_strategy '
|
||||||
'is defined')
|
'is defined'))
|
||||||
|
|
||||||
if isinstance(security_strategy, six.string_types):
|
if isinstance(security_strategy, six.string_types):
|
||||||
security_strategy = security_strategy.encode('utf-8')
|
security_strategy = security_strategy.encode('utf-8')
|
||||||
@ -1888,7 +1897,7 @@ class _SecureTokenCache(_TokenCache):
|
|||||||
# unprotect_data will return None if raw_cached is None
|
# unprotect_data will return None if raw_cached is None
|
||||||
return memcache_crypt.unprotect_data(context, data)
|
return memcache_crypt.unprotect_data(context, data)
|
||||||
except Exception:
|
except Exception:
|
||||||
msg = 'Failed to decrypt/verify cache data'
|
msg = _LE('Failed to decrypt/verify cache data')
|
||||||
self._LOG.exception(msg)
|
self._LOG.exception(msg)
|
||||||
|
|
||||||
# this should have the same effect as data not
|
# this should have the same effect as data not
|
||||||
|
37
keystonemiddleware/i18n.py
Normal file
37
keystonemiddleware/i18n.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# Copyright 2014 IBM Corp.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
"""oslo.i18n integration module.
|
||||||
|
|
||||||
|
See http://docs.openstack.org/developer/oslo.i18n/usage.html .
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from oslo import i18n
|
||||||
|
|
||||||
|
|
||||||
|
_translators = i18n.TranslatorFactory(domain='keystonemiddleware')
|
||||||
|
|
||||||
|
# The primary translation function using the well-known name "_"
|
||||||
|
_ = _translators.primary
|
||||||
|
|
||||||
|
# Translators for log levels.
|
||||||
|
#
|
||||||
|
# The abbreviated names are meant to reflect the usual use of a short
|
||||||
|
# name like '_'. The "L" is for "log" and the other letter comes from
|
||||||
|
# the level.
|
||||||
|
_LI = _translators.log_info
|
||||||
|
_LW = _translators.log_warning
|
||||||
|
_LE = _translators.log_error
|
||||||
|
_LC = _translators.log_critical
|
@ -39,6 +39,8 @@ import requests
|
|||||||
import six
|
import six
|
||||||
from six.moves import urllib
|
from six.moves import urllib
|
||||||
|
|
||||||
|
from keystonemiddleware.i18n import _, _LI
|
||||||
|
|
||||||
|
|
||||||
PROTOCOL_NAME = 'S3 Token Authentication'
|
PROTOCOL_NAME = 'S3 Token Authentication'
|
||||||
|
|
||||||
@ -67,7 +69,8 @@ def _split_path(path, minsegs=1, maxsegs=None, rest_with_last=False):
|
|||||||
if not maxsegs:
|
if not maxsegs:
|
||||||
maxsegs = minsegs
|
maxsegs = minsegs
|
||||||
if minsegs > maxsegs:
|
if minsegs > maxsegs:
|
||||||
raise ValueError('minsegs > maxsegs: %d > %d' % (minsegs, maxsegs))
|
raise ValueError(_('minsegs > maxsegs: %(min)d > %(max)d)') %
|
||||||
|
{'min': minsegs, 'max': maxsegs})
|
||||||
if rest_with_last:
|
if rest_with_last:
|
||||||
segs = path.split('/', maxsegs)
|
segs = path.split('/', maxsegs)
|
||||||
minsegs += 1
|
minsegs += 1
|
||||||
@ -75,7 +78,7 @@ def _split_path(path, minsegs=1, maxsegs=None, rest_with_last=False):
|
|||||||
count = len(segs)
|
count = len(segs)
|
||||||
if (segs[0] or count < minsegs or count > maxsegs or
|
if (segs[0] or count < minsegs or count > maxsegs or
|
||||||
'' in segs[1:minsegs]):
|
'' in segs[1:minsegs]):
|
||||||
raise ValueError('Invalid path: %s' % urllib.parse.quote(path))
|
raise ValueError(_('Invalid path: %s') % urllib.parse.quote(path))
|
||||||
else:
|
else:
|
||||||
minsegs += 1
|
minsegs += 1
|
||||||
maxsegs += 1
|
maxsegs += 1
|
||||||
@ -84,7 +87,7 @@ def _split_path(path, minsegs=1, maxsegs=None, rest_with_last=False):
|
|||||||
if (segs[0] or count < minsegs or count > maxsegs + 1 or
|
if (segs[0] or count < minsegs or count > maxsegs + 1 or
|
||||||
'' in segs[1:minsegs] or
|
'' in segs[1:minsegs] or
|
||||||
(count == maxsegs + 1 and segs[maxsegs])):
|
(count == maxsegs + 1 and segs[maxsegs])):
|
||||||
raise ValueError('Invalid path: %s' % urllib.parse.quote(path))
|
raise ValueError(_('Invalid path: %s') % urllib.parse.quote(path))
|
||||||
segs = segs[1:maxsegs]
|
segs = segs[1:maxsegs]
|
||||||
segs.extend([None] * (maxsegs - 1 - len(segs)))
|
segs.extend([None] * (maxsegs - 1 - len(segs)))
|
||||||
return segs
|
return segs
|
||||||
@ -149,7 +152,7 @@ class S3Token(object):
|
|||||||
headers=headers, data=creds_json,
|
headers=headers, data=creds_json,
|
||||||
verify=self._verify)
|
verify=self._verify)
|
||||||
except requests.exceptions.RequestException as e:
|
except requests.exceptions.RequestException as e:
|
||||||
self._logger.info('HTTP connection exception: %s', e)
|
self._logger.info(_LI('HTTP connection exception: %s'), e)
|
||||||
resp = self._deny_request('InvalidURI')
|
resp = self._deny_request('InvalidURI')
|
||||||
raise ServiceError(resp)
|
raise ServiceError(resp)
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
Babel>=1.3
|
Babel>=1.3
|
||||||
iso8601>=0.1.9
|
iso8601>=0.1.9
|
||||||
oslo.config>=1.4.0 # Apache-2.0
|
oslo.config>=1.4.0 # Apache-2.0
|
||||||
|
oslo.i18n>=1.0.0 # Apache-2.0
|
||||||
oslo.serialization>=1.0.0 # Apache-2.0
|
oslo.serialization>=1.0.0 # Apache-2.0
|
||||||
oslo.utils>=1.0.0 # Apache-2.0
|
oslo.utils>=1.0.0 # Apache-2.0
|
||||||
pbr>=0.6,!=0.7,<1.0
|
pbr>=0.6,!=0.7,<1.0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user