summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2011-09-21 17:46:59 +0000
committerGerrit Code Review <review@openstack.org>2011-09-21 17:46:59 +0000
commit856ddbcdfc0172ff764510496ed4bfbc0f70d389 (patch)
tree211b425b9d00de0af9eaf5060e14d57ad4d1439a
parent14ab2a2421f2420e2ce3ca54913755ff1501a736 (diff)
parent50b01f5e2f425074288123456a41704a9dcfe9f9 (diff)
Merge "Add code removed in https://code.launchpad.net/~vishvananda/nova/remove-keystone-middleware/+merge/76297 to keystone."
-rw-r--r--examples/paste/nova-api-paste.ini5
-rw-r--r--keystone/middleware/ec2_token.py89
-rw-r--r--keystone/middleware/nova_keystone_context.py62
3 files changed, 153 insertions, 3 deletions
diff --git a/examples/paste/nova-api-paste.ini b/examples/paste/nova-api-paste.ini
index 56992013..9e76dc29 100644
--- a/examples/paste/nova-api-paste.ini
+++ b/examples/paste/nova-api-paste.ini
@@ -37,7 +37,7 @@ paste.filter_factory = nova.api.ec2:RequestLogging.factory
paste.filter_factory = nova.api.ec2:Lockout.factory
[filter:totoken]
-paste.filter_factory = nova.api.ec2:ToToken.factory
+paste.filter_factory = keystone.middleware.ec2_token:EC2Token.factory
[filter:ec2noauth]
paste.filter_factory = nova.api.ec2:NoAuth.factory
@@ -113,7 +113,7 @@ paste.app_factory = nova.api.openstack.versions:Versions.factory
##########
[filter:keystonecontext]
-paste.filter_factory = nova.api.auth:KeystoneContext.factory
+paste.filter_factory = keystone.middleware.nova_keystone_context:NovaKeystoneContext.factory
[filter:authtoken]
paste.filter_factory = keystone.middleware.auth_token:filter_factory
@@ -125,4 +125,3 @@ auth_port = 5001
auth_protocol = http
auth_uri = http://127.0.0.1:5000/
admin_token = 999888777666
-
diff --git a/keystone/middleware/ec2_token.py b/keystone/middleware/ec2_token.py
new file mode 100644
index 00000000..d7d762d8
--- /dev/null
+++ b/keystone/middleware/ec2_token.py
@@ -0,0 +1,89 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2010 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# 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.
+"""
+Starting point for routing EC2 requests.
+
+"""
+
+from urlparse import urlparse
+
+from eventlet.green import httplib
+import webob.dec
+import webob.exc
+
+from nova import flags
+from nova import utils
+from nova import wsgi
+
+
+FLAGS = flags.FLAGS
+flags.DEFINE_string('keystone_ec2_url',
+ 'http://localhost:5000/v2.0/ec2tokens',
+ 'URL to get token from ec2 request.')
+
+
+class EC2Token(wsgi.Middleware):
+ """Authenticate an EC2 request with keystone and convert to token."""
+
+ @webob.dec.wsgify(RequestClass=wsgi.Request)
+ def __call__(self, req):
+ # Read request signature and access id.
+ try:
+ signature = req.params['Signature']
+ access = req.params['AWSAccessKeyId']
+ except KeyError:
+ raise webob.exc.HTTPBadRequest()
+
+ # Make a copy of args for authentication and signature verification.
+ auth_params = dict(req.params)
+ # Not part of authentication args
+ auth_params.pop('Signature')
+
+ # Authenticate the request.
+ creds = {'ec2Credentials': {'access': access,
+ 'signature': signature,
+ 'host': req.host,
+ 'verb': req.method,
+ 'path': req.path,
+ 'params': auth_params,
+ }}
+ creds_json = utils.dumps(creds)
+ headers = {'Content-Type': 'application/json'}
+
+ # Disable "has no x member" pylint error
+ # for httplib and urlparse
+ # pylint: disable-msg=E1101
+ o = urlparse(FLAGS.keystone_ec1_url)
+ if o.scheme == "http":
+ conn = httplib.HTTPConnection(o.netloc)
+ else:
+ conn = httplib.HTTPSConnection(o.netloc)
+ conn.request('POST', o.path, body=creds_json, headers=headers)
+ response = conn.getresponse().read()
+ conn.close()
+
+ # NOTE(vish): We could save a call to keystone by
+ # having keystone return token, tenant,
+ # user, and roles from this call.
+ result = utils.loads(response)
+ # TODO(vish): check for errors
+
+ token_id = result['auth']['token']['id']
+ # Authenticated!
+ req.headers['X-Auth-Token'] = token_id
+ return self.application
diff --git a/keystone/middleware/nova_keystone_context.py b/keystone/middleware/nova_keystone_context.py
new file mode 100644
index 00000000..646ba9bd
--- /dev/null
+++ b/keystone/middleware/nova_keystone_context.py
@@ -0,0 +1,62 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright (c) 2011 OpenStack, LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+"""
+Nova Auth Middleware.
+
+"""
+
+import webob.dec
+import webob.exc
+
+from nova import context
+from nova import flags
+from nova import wsgi
+
+
+FLAGS = flags.FLAGS
+flags.DECLARE('use_forwarded_for', 'nova.api.auth')
+
+
+class NovaKeystoneContext(wsgi.Middleware):
+ """Make a request context from keystone headers"""
+
+ @webob.dec.wsgify(RequestClass=wsgi.Request)
+ def __call__(self, req):
+ try:
+ user_id = req.headers['X_USER']
+ except KeyError:
+ return webob.exc.HTTPUnauthorized()
+ # get the roles
+ roles = [r.strip() for r in req.headers.get('X_ROLE', '').split(',')]
+ project_id = req.headers['X_TENANT']
+ # Get the auth token
+ auth_token = req.headers.get('X_AUTH_TOKEN',
+ req.headers.get('X_STORAGE_TOKEN'))
+
+ # Build a context, including the auth_token...
+ remote_address = getattr(req, 'remote_address', '127.0.0.1')
+ remote_address = req.remote_addr
+ if FLAGS.use_forwarded_for:
+ remote_address = req.headers.get('X-Forwarded-For', remote_address)
+ ctx = context.RequestContext(user_id,
+ project_id,
+ roles=roles,
+ auth_token=auth_token,
+ strategy='keystone',
+ remote_address=remote_address)
+
+ req.environ['nova.context'] = ctx
+ return self.application