summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Prince <dan.prince@rackspace.com>2012-02-01 15:17:26 -0500
committerDan Prince <dan.prince@rackspace.com>2012-02-02 17:24:17 -0500
commitf76477c7b19aeade22ef00bccc1b652cc37d7349 (patch)
tree0d6fab3dbbe35fe8496cfa3d652a08825fecced3
parentd2e6f63fe107c17e344337b8db030733ed9bbb2e (diff)
Update auth_token middleware to support creds.
Updates to the auth_token middleware to support admin_user and admin_password in addition to the existing admin_token. If an admin_token isn't specified then a call to obtain the admin_token is made. If an admin token expires the username and password can also be used to obtain a fresh token. Also, added a test for case for middleware where token isn't specified. Fixes LP Bug #923573. Change-Id: I643efec310cbb9a175607cc17f0c077f261b1d6d
-rw-r--r--keystone/middleware/auth_token.py64
-rwxr-xr-xkeystone/middleware/quantum_auth_token.py6
-rw-r--r--keystone/test/client/test_middleware.py28
-rw-r--r--keystone/test/functional/common.py4
4 files changed, 78 insertions, 24 deletions
diff --git a/keystone/middleware/auth_token.py b/keystone/middleware/auth_token.py
index d3ccc3a5..8cde88a6 100644
--- a/keystone/middleware/auth_token.py
+++ b/keystone/middleware/auth_token.py
@@ -101,7 +101,7 @@ from dateutil import parser
import errno
import eventlet
from eventlet import wsgi
-from httplib import HTTPException
+import httplib
import json
# memcache is imported in __init__ if memcache caching is configured
import logging
@@ -194,6 +194,8 @@ class AuthProtocol(object):
# Credentials used to verify this component with the Auth service since
# validating tokens is a privileged call
self.admin_token = conf.get('admin_token')
+ self.admin_user = conf.get('admin_user', None)
+ self.admin_password = conf.get('admin_password', None)
# Certificate file and key file used to authenticate with Keystone
# server
self.cert_file = conf.get('certfile', None)
@@ -265,7 +267,7 @@ class AuthProtocol(object):
# the keystone server
try:
self.osksvalidate = self._supports_osksvalidate()
- except (HTTPException, StandardError):
+ except (httplib.HTTPException, StandardError):
pass
#Prep headers to forward request to local or remote downstream service
@@ -427,7 +429,38 @@ class AuthProtocol(object):
return HTTPUnauthorized()(env,
start_response)
- def _verify_claims(self, env, claims):
+ def _build_token_uri(self):
+ return '/v2.0/tokens/%s' % self.service_id_querystring
+
+ def _get_admin_auth_token(self, username, password):
+ """
+ This function gets an admin auth token to be used by this service to
+ validate a user's token. Validate_token is a priviledged call so
+ it needs to be authenticated by a service that is calling it
+ """
+ headers = {
+ "Content-type": "application/json",
+ "Accept": "application/json"}
+ params = {
+ "auth": {
+ "passwordCredentials": {
+ "username": username,
+ "password": password,
+ }
+ }
+ }
+ if self.auth_protocol == "http":
+ conn = httplib.HTTPConnection(self.auth_host, self.auth_port)
+ else:
+ conn = httplib.HTTPSConnection(self.auth_host, self.auth_port,
+ cert_file=self.cert_file)
+ conn.request("POST", self._build_token_uri(), json.dumps(params),
+ headers=headers)
+ response = conn.getresponse()
+ data = response.read()
+ return data
+
+ def _verify_claims(self, env, claims, retry=True):
"""Verify claims and extract identity information, if applicable."""
cached_claims = self._cache_get(env, claims)
@@ -444,10 +477,10 @@ class AuthProtocol(object):
# Step 1: We need to auth with the keystone service, so get an
# admin token
- #TODO(ziad): Need to properly implement this, where to store creds
- # for now using token from ini
- #auth = self.get_admin_auth_token("admin", "secrete", "1")
- #admin_token = json.loads(auth)["auth"]["token"]["id"]
+ if not self.admin_token:
+ auth = self._get_admin_auth_token(self.admin_user,
+ self.admin_password)
+ self.admin_token = json.loads(auth)["access"]["token"]["id"]
# Step 2: validate the user's token with the auth service
# since this is a priviledged op,m we need to auth ourselves
@@ -467,11 +500,6 @@ class AuthProtocol(object):
logger.debug("Connecting to %s://%s:%s to check claims" % (
self.auth_protocol, self.auth_host, self.auth_port))
- ##TODO(ziad):we need to figure out how to auth to keystone
- #since validate_token is a priviledged call
- #Khaled's version uses creds to get a token
- # "X-Auth-Token": admin_token}
- # we're using a test token from the ini file for now
try:
conn = http_connect(self.auth_host, self.auth_port, 'GET',
path,
@@ -504,9 +532,13 @@ class AuthProtocol(object):
datetime.strftime(time.time(),
EXPIRE_TIME_FORMAT)},
valid=False)
- # Keystone rejected claim
- logger.debug("Failing the validation")
- raise ValidationFailed()
+ if retry:
+ self.admin_token = None
+ return self._verify_claims(env, claims, False)
+ else:
+ # Keystone rejected claim
+ logger.debug("Failing the validation")
+ raise ValidationFailed()
token_info = json.loads(data)
@@ -642,7 +674,7 @@ class AuthProtocol(object):
logger.debug("Falling back to core API behavior (using tokens in "
"URL)")
return False
- except HTTPException as exc:
+ except httplib.HTTPException as exc:
logger.exception("Error trying to detect extensions.")
logger.debug("Falling back to core API behavior (using tokens in "
"URL)")
diff --git a/keystone/middleware/quantum_auth_token.py b/keystone/middleware/quantum_auth_token.py
index 357dcac0..6d027c41 100755
--- a/keystone/middleware/quantum_auth_token.py
+++ b/keystone/middleware/quantum_auth_token.py
@@ -127,9 +127,9 @@ class AuthProtocol(object):
logger.debug("Authentication Service:%s", self.auth_location)
# Credentials used to verify this component with the Auth service
# since validating tokens is a privileged call
- self.admin_user = conf.get('auth_admin_user')
- self.admin_password = conf.get('auth_admin_password')
- self.admin_token = conf.get('auth_admin_token')
+ self.admin_user = conf.get('admin_user')
+ self.admin_password = conf.get('admin_password')
+ self.admin_token = conf.get('admin_token')
# bind to one or more service instances
service_ids = conf.get('service_ids')
self.serviceId_qs = ''
diff --git a/keystone/test/client/test_middleware.py b/keystone/test/client/test_middleware.py
index bf3b46d4..543e0b70 100644
--- a/keystone/test/client/test_middleware.py
+++ b/keystone/test/client/test_middleware.py
@@ -1,6 +1,8 @@
import unittest2 as unittest
+import uuid
import keystone.common.exception
+import keystone.backends.api as db_api
from keystone.test.functional import common
from keystone.test import client as client_tests
@@ -19,6 +21,26 @@ class TestAuthTokenMiddleware(common.MiddlewareTestCase):
super(TestAuthTokenMiddleware, self).setUp(auth_token)
+class TestAuthTokenMiddlewareWithNoAdminToken(common.MiddlewareTestCase):
+ """
+ Tests for Keystone WSGI middleware: Auth Token
+ """
+
+ def setUp(self):
+ settings = {'delay_auth_decision': '0',
+ 'auth_host': client_tests.TEST_TARGET_SERVER_ADMIN_ADDRESS,
+ 'auth_port': client_tests.TEST_TARGET_SERVER_ADMIN_PORT,
+ 'auth_protocol':
+ client_tests.TEST_TARGET_SERVER_ADMIN_PROTOCOL,
+ 'auth_uri': ('%s://%s:%s/' % \
+ (client_tests.TEST_TARGET_SERVER_SERVICE_PROTOCOL,
+ client_tests.TEST_TARGET_SERVER_SERVICE_ADDRESS,
+ client_tests.TEST_TARGET_SERVER_SERVICE_PORT)),
+ 'admin_user': self.admin_username,
+ 'admin_password': self.admin_password}
+ super(TestAuthTokenMiddlewareWithNoAdminToken, self).setUp(auth_token,
+ settings)
+
#
# Glance
#
@@ -65,9 +87,9 @@ class TestQuantumMiddleware(common.MiddlewareTestCase):
client_tests.TEST_TARGET_SERVER_SERVICE_ADDRESS,
client_tests.TEST_TARGET_SERVER_SERVICE_PORT)),
'auth_version': '2.0',
- 'auth_admin_token': self.admin_token,
- 'auth_admin_user': self.admin_username,
- 'auth_admin_password': self.admin_password}
+ 'admin_token': self.admin_token,
+ 'admin_user': self.admin_username,
+ 'admin_password': self.admin_password}
super(TestQuantumMiddleware, self).setUp(quantum_auth_token, settings)
diff --git a/keystone/test/functional/common.py b/keystone/test/functional/common.py
index 12935ce3..80a10819 100644
--- a/keystone/test/functional/common.py
+++ b/keystone/test/functional/common.py
@@ -1596,8 +1596,8 @@ class MiddlewareTestCase(FunctionalTestCase):
client_tests.TEST_TARGET_SERVER_SERVICE_ADDRESS,
client_tests.TEST_TARGET_SERVER_SERVICE_PORT)),
'admin_token': self.admin_token,
- 'auth_admin_user': self.admin_username,
- 'auth_admin_password': self.admin_password}
+ 'admin_user': self.admin_username,
+ 'admin_password': self.admin_password}
cert_file = isSsl()
if cert_file:
settings['certfile'] = cert_file