Fix middleware logging for swift

Swift sets 'log_name' in the conf, and this can be used to set the
correct logger.  This patch moves the log configuration to
initialization so that the logger can be set appropriately and the
middleware will log to the swift proxy logs.  This also requires the
following review in swift to work:
https://review.openstack.org/#/c/17983/

Fixes bug #1089664

Change-Id: I315102ba277ac1f5ff92f4d79ae745bf53559328
This commit is contained in:
Chuck Thier
2012-12-12 17:11:34 -06:00
parent 095cdd1057
commit 665eeba82c

View File

@@ -136,7 +136,6 @@ except ImportError:
if not CONF:
from keystoneclient.openstack.common import cfg
CONF = cfg.CONF
LOG = logging.getLogger(__name__)
# alternative middleware configuration in the main application's
# configuration file e.g. in nova.conf
@@ -193,7 +192,8 @@ class AuthProtocol(object):
"""Auth Middleware that handles authenticating client calls."""
def __init__(self, app, conf):
LOG.info('Starting keystone auth_token middleware')
self.LOG = logging.getLogger(conf.get('log_name', __name__))
self.LOG.info('Starting keystone auth_token middleware')
self.conf = conf
self.app = app
@@ -226,8 +226,8 @@ class AuthProtocol(object):
self.signing_dirname = self._conf_get('signing_dir')
if self.signing_dirname is None:
self.signing_dirname = '%s/keystone-signing' % os.environ['HOME']
LOG.info('Using %s as cache directory for signing certificate' %
self.signing_dirname)
self.LOG.info('Using %s as cache directory for signing certificate' %
self.signing_dirname)
if (os.path.exists(self.signing_dirname) and
not os.access(self.signing_dirname, os.W_OK)):
raise ConfigurationError("unable to access signing dir %s" %
@@ -267,11 +267,12 @@ class AuthProtocol(object):
try:
import memcache
import iso8601
LOG.info('Using memcache for caching token')
self.LOG.info('Using memcache for caching token')
self._cache = memcache.Client(memcache_servers)
self._iso8601 = iso8601
except ImportError as e:
LOG.warn('disabled caching due to missing libraries %s', e)
self.LOG.warn(
'disabled caching due to missing libraries %s', e)
def _conf_get(self, name):
# try config from paste-deploy first
@@ -287,7 +288,7 @@ class AuthProtocol(object):
we can't authenticate.
"""
LOG.debug('Authenticating user token')
self.LOG.debug('Authenticating user token')
try:
self._remove_auth_headers(env)
user_token = self._get_user_token_from_header(env)
@@ -299,15 +300,16 @@ class AuthProtocol(object):
except InvalidUserToken:
if self.delay_auth_decision:
LOG.info('Invalid user token - deferring reject downstream')
self.LOG.info(
'Invalid user token - deferring reject downstream')
self._add_headers(env, {'X-Identity-Status': 'Invalid'})
return self.app(env, start_response)
else:
LOG.info('Invalid user token - rejecting request')
self.LOG.info('Invalid user token - rejecting request')
return self._reject_request(env, start_response)
except ServiceError as e:
LOG.critical('Unable to obtain admin token: %s' % e)
self.LOG.critical('Unable to obtain admin token: %s' % e)
resp = webob.exc.HTTPServiceUnavailable()
return resp(env, start_response)
@@ -330,8 +332,8 @@ class AuthProtocol(object):
'X-Tenant',
'X-Role',
)
LOG.debug('Removing headers from request environment: %s' %
','.join(auth_headers))
self.LOG.debug('Removing headers from request environment: %s' %
','.join(auth_headers))
self._remove_headers(env, auth_headers)
def _get_user_token_from_header(self, env):
@@ -347,7 +349,8 @@ class AuthProtocol(object):
if token:
return token
else:
LOG.warn("Unable to find authentication token in headers: %s", env)
self.LOG.warn(
"Unable to find authentication token in headers: %s", env)
raise InvalidUserToken('Unable to find token in headers')
def _reject_request(self, env, start_response):
@@ -408,7 +411,7 @@ class AuthProtocol(object):
response = conn.getresponse()
body = response.read()
except Exception as e:
LOG.error('HTTP connection exception: %s' % e)
self.LOG.error('HTTP connection exception: %s' % e)
raise ServiceError('Unable to communicate with keystone')
finally:
conn.close()
@@ -448,7 +451,7 @@ class AuthProtocol(object):
response = conn.getresponse()
body = response.read()
except Exception as e:
LOG.error('HTTP connection exception: %s' % e)
self.LOG.error('HTTP connection exception: %s' % e)
raise ServiceError('Unable to communicate with keystone')
finally:
conn.close()
@@ -456,7 +459,7 @@ class AuthProtocol(object):
try:
data = jsonutils.loads(body)
except ValueError:
LOG.debug('Keystone did not return json-encoded body')
self.LOG.debug('Keystone did not return json-encoded body')
data = {}
return response, data
@@ -490,10 +493,12 @@ class AuthProtocol(object):
datetime_expiry = timeutils.parse_isotime(expiry)
return (token, timeutils.normalize_time(datetime_expiry))
except (AssertionError, KeyError):
LOG.warn("Unexpected response from keystone service: %s", data)
self.LOG.warn(
"Unexpected response from keystone service: %s", data)
raise ServiceError('invalid json response')
except (ValueError):
LOG.warn("Unable to parse expiration time from token: %s", data)
self.LOG.warn(
"Unable to parse expiration time from token: %s", data)
raise ServiceError('invalid json response')
def _validate_user_token(self, user_token, retry=True):
@@ -519,9 +524,9 @@ class AuthProtocol(object):
self._cache_put(token_id, data)
return data
except Exception as e:
LOG.debug('Token validation failure.', exc_info=True)
self.LOG.debug('Token validation failure.', exc_info=True)
self._cache_store_invalid(user_token)
LOG.warn("Authorization failed for token %s", user_token)
self.LOG.warn("Authorization failed for token %s", user_token)
raise InvalidUserToken('Token authorization failed')
def _build_user_headers(self, token_info):
@@ -636,15 +641,15 @@ class AuthProtocol(object):
key = 'tokens/%s' % token
cached = self._cache.get(key)
if cached == 'invalid':
LOG.debug('Cached Token %s is marked unauthorized', token)
self.LOG.debug('Cached Token %s is marked unauthorized', token)
raise InvalidUserToken('Token authorization failed')
if cached:
data, expires = cached
if time.time() < float(expires):
LOG.debug('Returning cached token %s', token)
self.LOG.debug('Returning cached token %s', token)
return data
else:
LOG.debug('Cached Token %s seems expired', token)
self.LOG.debug('Cached Token %s seems expired', token)
def _cache_put(self, token, data):
"""Put token data into the cache.
@@ -658,9 +663,9 @@ class AuthProtocol(object):
timestamp = data['access']['token']['expires']
expires = self._iso8601.parse_date(timestamp).strftime('%s')
else:
LOG.error('invalid token format')
self.LOG.error('invalid token format')
return
LOG.debug('Storing %s token in memcache', token)
self.LOG.debug('Storing %s token in memcache', token)
self._cache.set(key,
(data, expires),
time=self.token_cache_time)
@@ -669,7 +674,8 @@ class AuthProtocol(object):
"""Store invalid token in cache."""
if self._cache:
key = 'tokens/%s' % token
LOG.debug('Marking token %s as unauthorized in memcache', token)
self.LOG.debug(
'Marking token %s as unauthorized in memcache', token)
self._cache.set(key,
'invalid',
time=self.token_cache_time)
@@ -703,20 +709,21 @@ class AuthProtocol(object):
# FIXME(ja): I'm assuming the 404 status means that user_token is
# invalid - not that the admin_token is invalid
self._cache_store_invalid(user_token)
LOG.warn("Authorization failed for token %s", user_token)
self.LOG.warn("Authorization failed for token %s", user_token)
raise InvalidUserToken('Token authorization failed')
if response.status == 401:
LOG.info('Keystone rejected admin token %s, resetting', headers)
self.LOG.info(
'Keystone rejected admin token %s, resetting', headers)
self.admin_token = None
else:
LOG.error('Bad response code while validating token: %s' %
response.status)
self.LOG.error('Bad response code while validating token: %s' %
response.status)
if retry:
LOG.info('Retrying validation')
self.LOG.info('Retrying validation')
return self._validate_user_token(user_token, False)
else:
LOG.warn("Invalid user token: %s. Keystone response: %s.",
user_token, data)
self.LOG.warn("Invalid user token: %s. Keystone response: %s.",
user_token, data)
raise InvalidUserToken()
@@ -730,8 +737,8 @@ class AuthProtocol(object):
token_id = utils.hash_signed_token(signed_text)
for revoked_id in revoked_ids:
if token_id == revoked_id:
LOG.debug('Token %s is marked as having been revoked',
token_id)
self.LOG.debug('Token %s is marked as having been revoked',
token_id)
return True
return False
@@ -813,8 +820,9 @@ class AuthProtocol(object):
additional_headers=headers)
if response.status == 401:
if retry:
LOG.info('Keystone rejected admin token %s, resetting admin '
'token', headers)
self.LOG.info(
'Keystone rejected admin token %s, resetting admin token',
headers)
self.admin_token = None
return self.fetch_revocation_list(retry=False)
if response.status != 200:
@@ -832,7 +840,8 @@ class AuthProtocol(object):
certfile.write(data)
certfile.close()
except (AssertionError, KeyError):
LOG.warn("Unexpected response from keystone service: %s", data)
self.LOG.warn(
"Unexpected response from keystone service: %s", data)
raise ServiceError('invalid json response')
def fetch_ca_cert(self):
@@ -844,7 +853,8 @@ class AuthProtocol(object):
certfile.write(data)
certfile.close()
except (AssertionError, KeyError):
LOG.warn("Unexpected response from keystone service: %s", data)
self.LOG.warn(
"Unexpected response from keystone service: %s", data)
raise ServiceError('invalid json response')