Addressing comments from Ziad and Somik

This commit is contained in:
Salvatore Orlando 2011-08-23 17:47:45 +01:00
parent d3ff660f78
commit 667dab4e83
4 changed files with 62 additions and 12 deletions

37
README
View File

@ -84,6 +84,43 @@ $ export TENANT=t1
$ PYTHONPATH=. python quantum/cli.py -v create_net $TENANT network1
Created a new Virtual Network with ID:e754e7c0-a8eb-40e5-861a-b182d30c3441
# -- Authentication and Authorization
Requests to Quantum API are authenticated with the Keystone identity service
using a token-based authentication protocol.
A user should first authenticate with Keystone, supplying user credentials;
the Keystone service will return an authentication token, together with
informations concerning token expirations and endpoint where that token can
be used.
The authentication token must be included in every request for the Quantum
API, in the 'X_AUTH_TOKEN' header. Quantum will look for the authentication
token in this header, and validate it with the Keystone service.
In order to validate authentication tokens, Quantum uses Keystone's
administrative API. It therefore requires credentials for an administrative
user, which can be specified in Quantum's configuration file
(etc/quantum.conf)
Either username and password, or an authentication token for an administrative
user can be specified in the configuration file:
- Credentials:
admin_user = admin
admin_password = secrete
- Admin token:
admin_token = 9a82c95a-99e9-4c3a-b5ee-199f6ba7ff04
As of the current release, any user for a tenant is allowed to perform
every operation on the networks owned by the tenant itself, except for
plugging interfaces. In order to perform such operation, the user must have
the Quantum:NetworkAdmin roles. Roles can be configured in Keystone using
the administrative API.
# -- Writing your own Quantum plug-in
If you wish the write your own Quantum plugin, please refer to some concrete as

View File

@ -20,10 +20,11 @@ use = egg:Paste#urlmap
/v0.1: quantumapi
[pipeline:quantumapi]
# To enable keystone integration comment the following line and
# To disable keystone integration comment the following line and
# uncomment the next one
pipeline = extensions quantumapiapp
#pipeline = authN authZ extensions quantumapiapp
pipeline = authN authZ extensions quantumapiapp
#pipeline = extensions quantumapiapp
[filter:authN]
paste.filter_factory = quantum.common.authentication:filter_factory

View File

@ -223,13 +223,11 @@ class AuthProtocol(object):
def _reject_request(self):
"""Redirect client to auth server"""
return HTTPUseProxy(location=self.auth_location)(self.env,
self.start_response)
return HTTPUnauthorized()(self.env, self.start_response)
def _reject_claims(self):
"""Client sent bad claims"""
return HTTPUnauthorized()(self.env,
self.start_response)
return HTTPUnauthorized()(self.env, self.start_response)
def _validate_claims(self, claims):
"""Validate claims, and provide identity information if applicable """

View File

@ -31,6 +31,9 @@ import logging
from webob.exc import HTTPUnauthorized, HTTPForbidden
LOG = logging.getLogger('quantum.common.authorization')
TENANT_HEADER = "HTTP_X_TENANT"
ROLE_HEADER = "HTTP_X_ROLE"
ADMIN_ROLE = "Quantum:NetworkAdmin"
#TODO(salvatore-orlando): This class should extend Middleware class
@ -54,12 +57,11 @@ class QuantumAuthorization(object):
# should already have been authenticated with Keystone
self.headers = req.copy()
LOG.debug("Looking for X_TENANT header")
LOG.debug("Headers:%s" % self.headers)
if not "HTTP_X_TENANT" in self.headers:
if not TENANT_HEADER in self.headers:
# This is bad, very bad
return self._reject()
LOG.debug("X_TENANT header found:%s", self.headers['HTTP_X_TENANT'])
auth_tenant_id = self.headers['HTTP_X_TENANT']
LOG.debug("X_TENANT header found:%s", self.headers[TENANT_HEADER])
auth_tenant_id = self.headers[TENANT_HEADER]
path = self.req['PATH_INFO']
parts = path.split('/')
LOG.debug("Request parts:%s", parts)
@ -70,7 +72,19 @@ class QuantumAuthorization(object):
if auth_tenant_id != req_tenant_id:
# This is bad, very bad
return self._forbid()
# Are you trying to operate on an attachment?
# If yes, you must be Quantum:NetworkAdmin
if parts[len(parts) - 1] == "attachment":
LOG.debug("Looking for X_ROLE header")
LOG.debug("Headers:%s", self.headers)
if not ROLE_HEADER in self.headers:
#This is bad as you definetely are not an administrator
return self._forbid()
LOG.debug("X_ROLE header found:%s", self.headers[ROLE_HEADER])
roles = self.headers[ROLE_HEADER].split(',')
if not ADMIN_ROLE in roles:
# Sorry, you're not and admin
return self._forbid()
# Okay, authorize it - pass downstream
return self.app(self.req, self.start_response)