From: Salvatore Orlando Date: Tue, 23 Aug 2011 16:47:45 +0000 (+0100) Subject: Addressing comments from Ziad and Somik X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=667dab4e83164902e3f78cd3b650dbfb882391b7;p=openstack-build%2Fneutron-build.git Addressing comments from Ziad and Somik --- diff --git a/README b/README index c7877ef6f..be695302a 100644 --- a/README +++ b/README @@ -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 diff --git a/etc/quantum.conf b/etc/quantum.conf index fe6ce8f84..ab6349639 100644 --- a/etc/quantum.conf +++ b/etc/quantum.conf @@ -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 diff --git a/quantum/common/authentication.py b/quantum/common/authentication.py index 3f4b52328..6f849249b 100755 --- a/quantum/common/authentication.py +++ b/quantum/common/authentication.py @@ -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 """ diff --git a/quantum/common/authorization.py b/quantum/common/authorization.py index 6fb59780a..408b5c6fc 100644 --- a/quantum/common/authorization.py +++ b/quantum/common/authorization.py @@ -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)