Add version to the cert rpc API.

Part of blueprint versioned-rpc-apis.

Change-Id: Iea00a2e82eef7ca7b3ffef438e81e5b4fcca7751
This commit is contained in:
Russell Bryant
2012-05-07 14:13:44 -04:00
parent 8ed3059cb4
commit 1b6aa2d1af
6 changed files with 200 additions and 17 deletions
@@ -19,6 +19,7 @@ import webob.exc
from nova.api.openstack import extensions
from nova.api.openstack import wsgi
from nova.api.openstack import xmlutil
import nova.cert.rpcapi
from nova import flags
from nova import log as logging
from nova import network
@@ -64,6 +65,7 @@ class CertificatesController(object):
def __init__(self):
self.network_api = network.API()
self.cert_rpcapi = nova.cert.rpcapi.CertAPI()
super(CertificatesController, self).__init__()
@wsgi.serializers(xml=CertificateTemplate)
@@ -74,9 +76,8 @@ class CertificatesController(object):
if id != 'root':
msg = _("Only root certificate can be retrieved.")
raise webob.exc.HTTPNotImplemented(explanation=msg)
cert = rpc.call(context, FLAGS.cert_topic,
{"method": "fetch_ca",
"args": {"project_id": context.project_id}})
cert = self.cert_rpcapi.fetch_ca(context,
project_id=context.project_id)
return {'certificate': _translate_certificate_view(cert)}
@wsgi.serializers(xml=CertificateTemplate)
@@ -84,10 +85,8 @@ class CertificatesController(object):
"""Return a list of certificates."""
context = req.environ['nova.context']
authorize(context)
pk, cert = rpc.call(context, FLAGS.cert_topic,
{"method": "generate_x509_cert",
"args": {"user_id": context.user_id,
"project_id": context.project_id}})
pk, cert = self.cert_rpcapi.generate_x509_cert(context,
user_id=context.user_id, project_id=context.project_id)
context = req.environ['nova.context']
return {'certificate': _translate_certificate_view(cert, pk)}
+2
View File
@@ -36,6 +36,8 @@ FLAGS = flags.FLAGS
class CertManager(manager.Manager):
RPC_API_VERSION = '1.0'
def init_host(self):
crypto.ensure_ca_filesystem()
+71
View File
@@ -0,0 +1,71 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2012, Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Client side of the cert manager RPC API.
"""
from nova import flags
import nova.rpc.proxy
FLAGS = flags.FLAGS
class CertAPI(nova.rpc.proxy.RpcProxy):
'''Client side of the cert rpc API.
API version history:
1.0 - Initial version.
'''
RPC_API_VERSION = '1.0'
def __init__(self):
super(CertAPI, self).__init__(topic=FLAGS.cert_topic,
default_version=self.RPC_API_VERSION)
def revoke_certs_by_user(self, ctxt, user_id):
return self.call(ctxt, self.make_msg('revoke_certs_by_user',
user_id=user_id))
def revoke_certs_by_project(self, ctxt, project_id):
return self.call(ctxt, self.make_msg('revoke_certs_by_project',
project_id=project_id))
def revoke_certs_by_user_and_project(self, ctxt, user_id, project_id):
return self.call(ctxt,
self.make_msg('revoke_certs_by_user_and_project',
user_id=user_id, project_id=project_id))
def generate_x509_cert(self, ctxt, user_id, project_id):
return self.call(ctxt, self.make_msg('generate_x509_cert',
user_id=user_id,
project_id=project_id))
def fetch_ca(self, ctxt, project_id):
return self.call(ctxt, self.make_msg('fetch_ca',
project_id=project_id))
def fetch_crl(self, ctxt, project_id):
return self.call(ctxt, self.make_msg('fetch_crl',
project_id=project_id))
def decrypt_text(self, ctxt, project_id, text):
return self.call(ctxt, self.make_msg('decrypt_text',
project_id=project_id,
text=text))
+9 -10
View File
@@ -30,6 +30,7 @@ import eventlet
from lxml import etree
from nova.api.ec2 import ec2utils
import nova.cert.rpcapi
from nova import exception
from nova import flags
from nova import image
@@ -68,6 +69,7 @@ class S3ImageService(object):
"""Wraps an existing image service to support s3 based register."""
def __init__(self, service=None, *args, **kwargs):
self.cert_rpcapi = nova.cert.rpcapi.CertAPI()
self.service = service or image.get_default_image_service()
self.service.__init__(*args, **kwargs)
@@ -366,23 +368,20 @@ class S3ImageService(object):
return image
@staticmethod
def _decrypt_image(context, encrypted_filename, encrypted_key,
def _decrypt_image(self, context, encrypted_filename, encrypted_key,
encrypted_iv, decrypted_filename):
elevated = context.elevated()
try:
key = rpc.call(elevated, FLAGS.cert_topic,
{"method": "decrypt_text",
"args": {"project_id": context.project_id,
"text": base64.b64encode(encrypted_key)}})
key = self.cert_rpcapi.decrypt_text(elevated,
project_id=context.project_id,
text=base64.b64encode(encrypted_key))
except Exception, exc:
msg = _('Failed to decrypt private key: %s') % exc
raise exception.NovaException(msg)
try:
iv = rpc.call(elevated, FLAGS.cert_topic,
{"method": "decrypt_text",
"args": {"project_id": context.project_id,
"text": base64.b64encode(encrypted_iv)}})
iv = self.cert_rpcapi.decrypt_text(elevated,
project_id=context.project_id,
text=base64.b64encode(encrypted_iv))
except Exception, exc:
raise exception.NovaException(_('Failed to decrypt initialization '
'vector: %s') % exc)
+19
View File
@@ -0,0 +1,19 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2011 OpenStack LLC.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# NOTE(vish): this forces the fixtures from tests/__init.py:setup() to work
from nova.tests import *
+93
View File
@@ -0,0 +1,93 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2012, Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Unit Tests for nova.cert.rpcapi
"""
from nova.cert import rpcapi as cert_rpcapi
from nova import context
from nova import flags
from nova import rpc
from nova import test
FLAGS = flags.FLAGS
class CertRpcAPITestCase(test.TestCase):
def setUp(self):
super(CertRpcAPITestCase, self).setUp()
def tearDown(self):
super(CertRpcAPITestCase, self).tearDown()
def _test_cert_api(self, method, **kwargs):
ctxt = context.RequestContext('fake_user', 'fake_project')
rpcapi = cert_rpcapi.CertAPI()
expected_retval = 'foo'
expected_msg = rpcapi.make_msg(method, **kwargs)
expected_msg['version'] = rpcapi.RPC_API_VERSION
self.call_ctxt = None
self.call_topic = None
self.call_msg = None
self.call_timeout = None
def _fake_call(_ctxt, _topic, _msg, _timeout):
self.call_ctxt = _ctxt
self.call_topic = _topic
self.call_msg = _msg
self.call_timeout = _timeout
return expected_retval
self.stubs.Set(rpc, 'call', _fake_call)
retval = getattr(rpcapi, method)(ctxt, **kwargs)
self.assertEqual(retval, expected_retval)
self.assertEqual(self.call_ctxt, ctxt)
self.assertEqual(self.call_topic, FLAGS.cert_topic)
self.assertEqual(self.call_msg, expected_msg)
self.assertEqual(self.call_timeout, None)
def test_revoke_certs_by_user(self):
self._test_cert_api('revoke_certs_by_user', user_id='fake_user_id')
def test_revoke_certs_by_project(self):
self._test_cert_api('revoke_certs_by_project',
project_id='fake_project_id')
def test_revoke_certs_by_user_and_project(self):
self._test_cert_api('revoke_certs_by_user_and_project',
user_id='fake_user_id',
project_id='fake_project_id')
def test_generate_x509_cert(self):
self._test_cert_api('generate_x509_cert',
user_id='fake_user_id',
project_id='fake_project_id')
def test_fetch_ca(self):
self._test_cert_api('fetch_ca', project_id='fake_project_id')
def test_fetch_crl(self):
self._test_cert_api('fetch_crl', project_id='fake_project_id')
def test_decrypt_text(self):
self._test_cert_api('decrypt_text',
project_id='fake_project_id', text='blah')