Store credential ID for AccessKey and SignalResponder

These resources create an ec2 keypair, which when managed via the
keystone v3/credentials should be accessed via credential ID not
the access key ID, so store the credential ID for performing any
operations (get/update/delete) on the credential, as it's preferable
to having to do a brute-force lookup by access key (no way to filter
on the access key via v3/credentials)

Change-Id: I5995fb003c998fc2d7f331c6da7430adcab168b2
blueprint: keystone-v3-only
This commit is contained in:
Steven Hardy 2014-01-15 16:56:07 +00:00
parent ece8eefbc0
commit bc1a93c856
5 changed files with 23 additions and 5 deletions

View File

@ -226,6 +226,10 @@ class AccessKey(resource.Resource):
# SecretAccessKey attribute
db_api.resource_data_set(self, 'secret_key', kp.secret,
redact=True)
# Also store the credential ID as this should be used to manage
# the credential rather than the access key via v3/credentials
db_api.resource_data_set(self, 'credential_id', kp.id,
redact=True)
def handle_delete(self):
self._secret = None
@ -270,6 +274,9 @@ class AccessKey(resource.Resource):
# Store the key in resource_data
db_api.resource_data_set(self, 'secret_key',
kp.secret, redact=True)
# And the ID of the v3 credential
db_api.resource_data_set(self, 'credential_id',
kp.id, redact=True)
except Exception as ex:
logger.warn(_('could not get secret for %(username)s '
'Error:%(msg)s') % {

View File

@ -56,6 +56,8 @@ class SignalResponder(resource.Resource):
raise exception.Error(_("Error creating ec2 keypair for user %s") %
user_id)
else:
db_api.resource_data_set(self, 'credential_id', kp.id,
redact=True)
db_api.resource_data_set(self, 'access_key', kp.access,
redact=True)
db_api.resource_data_set(self, 'secret_key', kp.secret,
@ -80,7 +82,8 @@ class SignalResponder(resource.Resource):
self.keystone().delete_stack_user(user_id)
except clients.hkc.kc.exceptions.NotFound:
pass
for data_key in ('ec2_signed_url', 'access_key', 'secret_key'):
for data_key in ('ec2_signed_url', 'access_key', 'secret_key',
'credential_id'):
try:
db_api.resource_data_delete(self, data_key)
except exception.NotFound:

View File

@ -78,12 +78,14 @@ class FakeClient(object):
class FakeKeystoneClient(object):
def __init__(self, username='test_user', password='apassword',
user_id='1234', access='4567', secret='8901'):
user_id='1234', access='4567', secret='8901',
credential_id='abcdxyz'):
self.username = username
self.password = password
self.user_id = user_id
self.access = access
self.secret = secret
self.credential_id = credential_id
self.creds = None
self.auth_token = 'abcd1234'
@ -107,6 +109,7 @@ class FakeKeystoneClient(object):
if user_id == self.user_id:
if not self.creds:
class FakeCred(object):
id = self.credential_id
access = self.access
secret = self.secret
self.creds = FakeCred()

View File

@ -169,7 +169,9 @@ class SignalTest(HeatTestCase):
self.m.StubOutWithMock(clients.OpenStackClients, 'keystone')
clients.OpenStackClients.keystone().MultipleTimes().AndReturn(
fakes.FakeKeystoneClient(
access='anaccesskey', secret='verysecret'))
access='anaccesskey',
secret='verysecret',
credential_id='mycredential'))
self.m.ReplayAll()
self.stack.create()
@ -179,11 +181,12 @@ class SignalTest(HeatTestCase):
# Ensure the resource data has been stored correctly
rs_data = db_api.resource_data_get_all(rsrc)
self.assertEqual('mycredential', rs_data.get('credential_id'))
self.assertEqual('anaccesskey', rs_data.get('access_key'))
self.assertEqual('verysecret', rs_data.get('secret_key'))
self.assertEqual('1234', rs_data.get('user_id'))
self.assertEqual(rsrc.resource_id, rs_data.get('user_id'))
self.assertEqual(3, len(rs_data.keys()))
self.assertEqual(4, len(rs_data.keys()))
# And that we remove it on delete
scheduler.TaskRunner(rsrc.delete)()

View File

@ -299,7 +299,8 @@ class AccessKeyTest(UserPolicyTestCase):
# Ensure the resource data has been stored correctly
rs_data = db_api.resource_data_get_all(rsrc)
self.assertEqual(self.fc.secret, rs_data.get('secret_key'))
self.assertEqual(1, len(rs_data.keys()))
self.assertEqual(self.fc.credential_id, rs_data.get('credential_id'))
self.assertEqual(2, len(rs_data.keys()))
self.assertEqual(utils.PhysName(stack.name, 'CfnUser'),
rsrc.FnGetAtt('UserName'))
@ -332,6 +333,7 @@ class AccessKeyTest(UserPolicyTestCase):
# Delete the resource data for secret_key, to test that existing
# stacks which don't have the resource_data stored will continue
# working via retrieving the keypair from keystone
db_api.resource_data_delete(rsrc, 'credential_id')
db_api.resource_data_delete(rsrc, 'secret_key')
rs_data = db_api.resource_data_get_all(rsrc)
self.assertEqual(0, len(rs_data.keys()))