Make Keystone token validation works in devstack

Change-Id: Ie8a748bd06b2b76df577297ce27aa10a79c47232
This commit is contained in:
Frédéric Guillot 2016-12-09 12:15:43 -05:00
parent b31477b716
commit 3cc039afba
5 changed files with 82 additions and 26 deletions

View File

@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from keystoneauth1 import exceptions as keystoneauth1_exceptions
from keystoneauth1.identity import v3
from keystoneauth1 import session
from keystoneclient.v3 import client as keystone_client
@ -23,9 +24,14 @@ from almanach.core import exception
class KeystoneAuthentication(base_auth.BaseAuth):
def __init__(self, config):
auth = v3.Password(username=config.auth.keystone_username,
password=config.auth.keystone_password,
auth_url=config.auth.keystone_url)
auth = v3.Password(username=config.keystone_authtoken.username,
password=config.keystone_authtoken.password,
user_domain_id=config.keystone_authtoken.user_domain_id,
user_domain_name=config.keystone_authtoken.user_domain_name,
project_domain_name=config.keystone_authtoken.project_domain_name,
project_name=config.keystone_authtoken.project_name,
auth_url=config.keystone_authtoken.auth_url)
sess = session.Session(auth=auth)
self._client = keystone_client.Client(session=sess)
@ -33,9 +39,10 @@ class KeystoneAuthentication(base_auth.BaseAuth):
if token is None:
raise exception.AuthenticationFailureException('No token provided')
result = self._client.tokens.validate(token)
if not result:
raise exception.AuthenticationFailureException('Invalid token')
try:
if not self._client.tokens.validate(token):
raise exception.AuthenticationFailureException('Invalid token')
except keystoneauth1_exceptions.HttpError as e:
raise exception.AuthenticationFailureException(e.message)
return True

View File

@ -54,22 +54,37 @@ collector_opts = [
help='Delay in seconds between retries'),
]
keystone_opts = [
cfg.StrOpt('username',
help='Keystone service username'),
cfg.StrOpt('password',
secret=True,
help='Keystone service password'),
cfg.StrOpt('user_domain_id',
default='default',
help='Keystone service user domain ID'),
cfg.StrOpt('user_domain_name',
default='Default',
help='Keystone service user domain name'),
cfg.StrOpt('project_domain_name',
default='Default',
help='Keystone service project domain name'),
cfg.StrOpt('project_name',
default='service',
help='Keystone service project name'),
cfg.StrOpt('auth_url',
default='http://127.0.0.1:35357/v3',
help='Keystone API V3 admin endpoint'),
]
auth_opts = [
cfg.StrOpt('strategy',
default='private_key',
help='Authentication driver for the API'),
help='Authentication driver for the API: private_key or keystone'),
cfg.StrOpt('private_key',
secret=True,
default='secret',
help='Private key for private key authentication'),
cfg.StrOpt('keystone_username',
help='Keystone service username'),
cfg.StrOpt('keystone_password',
secret=True,
help='Keystone service password'),
cfg.StrOpt('keystone_url',
default='http://keystone_url:5000/v3',
help='Keystone URL'),
]
resource_opts = [
@ -86,6 +101,7 @@ CONF.register_opts(database_opts, group='database')
CONF.register_opts(api_opts, group='api')
CONF.register_opts(collector_opts, group='collector')
CONF.register_opts(auth_opts, group='auth')
CONF.register_opts(keystone_opts, group='keystone_authtoken')
CONF.register_opts(resource_opts, group='resources')
logging.register_options(CONF)
@ -97,6 +113,7 @@ def list_opts():
('database', database_opts),
('api', api_opts),
('collector', collector_opts),
('api.auth', auth_opts),
('auth', auth_opts),
('keystone_authtoken', keystone_opts),
('resources', resource_opts),
]

View File

@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from keystoneauth1 import exceptions as keystoneauth1_exceptions
import mock
from almanach.api.auth import keystone_auth
@ -43,6 +44,12 @@ class KeystoneAuthenticationTest(base.BaseTestCase):
self.assertRaises(exception.AuthenticationFailureException, self.driver.validate, token)
self.validation_mock.assert_called_once_with(token)
def test_with_http_error(self):
token = 'some keystone token'
self.validation_mock.side_effect = keystoneauth1_exceptions.HttpError(message='Some Error')
self.assertRaises(exception.AuthenticationFailureException, self.driver.validate, token)
self.validation_mock.assert_called_once_with(token)
def test_with_empty_token(self):
token = None
self.assertRaises(exception.AuthenticationFailureException, self.driver.validate, token)

View File

@ -35,9 +35,13 @@ function almanach_configure {
iniset $ALMANACH_CONF auth strategy keystone
iniset $ALMANACH_CONF auth keystone_username almanach
iniset $ALMANACH_CONF auth keystone_password $SERVICE_PASSWORD
iniset $ALMANACH_CONF auth keystone_url $KEYSTONE_SERVICE_URI/v2.0
iniset $ALMANACH_CONF keystone_authtoken username almanach
iniset $ALMANACH_CONF keystone_authtoken password $SERVICE_PASSWORD
iniset $ALMANACH_CONF keystone_authtoken user_domain_id default
iniset $ALMANACH_CONF keystone_authtoken user_domain_name $SERVICE_DOMAIN_NAME
iniset $ALMANACH_CONF keystone_authtoken project_domain_name $SERVICE_DOMAIN_NAME
iniset $ALMANACH_CONF keystone_authtoken project_name $SERVICE_PROJECT_NAME
iniset $ALMANACH_CONF keystone_authtoken auth_url $KEYSTONE_SERVICE_URI_V3
iniset $ALMANACH_CONF collector transport_url rabbit://stackrabbit:secret@localhost:5672

View File

@ -76,7 +76,7 @@ Protocol
The authentication mechanism use the HTTP header :code:`X-Auth-Token` to send a token.
This token is validated through Keystone or with the config file (private secret key).
:: code:: raw
.. code:: raw
GET /volume_types HTTP/1.1
X-Auth-Token: secret
@ -93,7 +93,7 @@ Private Key Authentication
The private secret key authentication is the default method.
In your config file, you have to define your private key in the field :code:`auth_token`:
:: code:: raw
.. code:: raw
[auth]
strategy = private_key
@ -106,13 +106,34 @@ Keystone Authentication
The token will be validated with Keystone.
To use this authentication backend you have to define the authentication strategy to :code:`keystone`.
:: code:: raw
.. code:: raw
[auth]
strategy = keystone
keystone_username = my_service_username
keystone_password = my_service_password
keystone_url = http://keystone_url:5000/v3
[keystone_authtoken]
# Keystone service username (string value)
username = almanach
# Keystone service password (string value)
password = secret
# Keystone service user domain ID (string value)
user_domain_id = default
# Keystone service user domain name (string value)
user_domain_name = Default
# Keystone service project domain name (string value)
project_domain_name = Default
# Keystone service project name (string value)
project_name = service
# Keystone API V3 admin endpoint (string value)
auth_url = http://127.0.0.1:35357/v3
RabbitMQ configuration