Fix admin requirement in trust middleware

Due to default policy.json settings in Keystone, a non-admin user is not
allowed to call 'list_users' or 'get_user' APIs. However, Senlin only
knows the user name but it needs a user ID to create the trust between
service requester and the 'senlin' user. The only workaround today is to
have Senlin query its own user ID using its user name. After this is
done, the trust middleware will use the service requester's credential
to raise the 'trust create' request to Keystone.

This necessitates two changes to the current code, one is to relax
Keystone's policy setting to allow a user with 'service' role to do user
list and user get (proposed here: https://review.openstack.org/181298);
the other one is to have Senlin trust middleware to raise user ID
checking request using 'senlin' credential.  This patch contains the
second part.

Since devstack doesn't provide a function to modify default policy
settings, we will wait to see if the patch to Keystone will be accepted.
If Keystone refuse to accept that change, we need to hack the devstack
plugin and 'setup-service' tool to modify the policy.json file.

Anyway, we need 'senlin' user to have a 'service' role in the
requester's domain (default to 'demo').

Change-Id: I87146a54f79e32a9175755f42da1e4406842c0b7
This commit is contained in:
tengqm 2015-05-08 03:53:50 -04:00
parent ec65d63770
commit 9c14bb6d60
3 changed files with 36 additions and 15 deletions

View File

@ -171,8 +171,8 @@ function create_senlin_accounts {
"$SERVICE_PROTOCOL://$SENLIN_API_HOST:$SENLIN_API_PORT/v1/\$(tenant_id)s"
fi
# senlin_stack_user role is for users created by Senlin
# get_or_create_role "senlin_cluster_user"
# get or adds 'service' role to 'senlin' on 'demo' project
get_or_add_user_project_role "service" "senlin" "demo"
}
# Restore xtrace

View File

@ -29,6 +29,31 @@ class TrustMiddleware(wsgi.Middleware):
The extracted information is filled into the request context.
Senlin engine will use this information for access control.
'''
def _get_service_user_id(self, ctx):
# Convert user name to user ID first
importutils.import_module('keystonemiddleware.auth_token')
admin_user = cfg.CONF.keystone_authtoken.admin_user
admin_passwd = cfg.CONF.keystone_authtoken.admin_password
params = {
'auth_url': ctx.auth_url,
'user_name': admin_user,
'password': admin_passwd,
# This is a hack, we need to know the domain name somehow
'user_domain_name': 'Default',
}
kc = keystone_v3.KeystoneClient(params)
try:
admin_id = kc.user_get_by_name(admin_user)
except exception.UserNotFound:
# This is unacceptable, treat it as a server error
msg = _("Failed Senlin user checking.")
raise webob.exc.HTTPInternalServerError(msg)
return admin_id
def _get_trust(self, ctx):
'''List trusts with current user as the trustor.'''
@ -44,26 +69,16 @@ class TrustMiddleware(wsgi.Middleware):
cred_exists = True
pass
admin_id = self._get_service_user_id(ctx)
params = {
'auth_url': ctx.auth_url,
'auth_token': ctx.auth_token,
'project': ctx.project,
'user': ctx.user,
}
kc = keystone_v3.KeystoneClient(params)
# Convert user name to user ID first
importutils.import_module('keystonemiddleware.auth_token')
admin_user = cfg.CONF.keystone_authtoken.admin_user
try:
admin_id = kc.user_get_by_name(admin_user)
except exception.UserNotFound:
# This is unacceptable, treat it as a server error
msg = _("Failed Senlin user checking.")
raise webob.exc.HTTPInternalServerError(msg)
try:
trusts = kc.trust_get_by_trustor(ctx.user, admin_id, ctx.project)
except exception.TrustNotFound:

View File

@ -36,6 +36,12 @@ openstack user create \
senlin
openstack role add \
service \
admin \
--user senlin \
--project service
# make sure 'senlin' has 'service' role in 'demo' project
openstack role add \
service \
--user senlin \
--project demo