Merge "Finish Initialization of CA Table when Barbican Starts"

This commit is contained in:
Jenkins 2015-09-18 19:57:09 +00:00 committed by Gerrit Code Review
commit 1a10c40f47
8 changed files with 39 additions and 50 deletions

View File

@ -256,6 +256,8 @@ class CertificateAuthoritiesController(controllers.ACLMixin):
self.project_repo = repo.get_project_repository()
self.validator = validators.NewCAValidator()
self.quota_enforcer = quota.QuotaEnforcer('cas', self.ca_repo)
# Populate the CA table at start up
cert_resources.refresh_certificate_resources()
def __getattr__(self, name):
route_table = {
@ -290,6 +292,9 @@ class CertificateAuthoritiesController(controllers.ACLMixin):
if plugin_ca_id is not None:
plugin_ca_id = parse.unquote_plus(plugin_ca_id)
# refresh CA table, in case plugin entries have expired
cert_resources.refresh_certificate_resources()
result = self.ca_repo.get_by_create_date(
offset_arg=kw.get('offset', 0),
limit_arg=kw.get('limit', None),

View File

@ -622,18 +622,25 @@ class CertificatePluginManager(named.NamedExtensionManager):
def refresh_ca_table(self):
"""Refreshes the CertificateAuthority table."""
session = self.ca_repo.get_session()
updates_made = False
for plugin in plugin_utils.get_active_plugins(self):
plugin_name = utils.generate_fullname_for(plugin)
cas, offset, limit, total = self.ca_repo.get_by_create_date(
plugin_name=plugin_name,
session=session,
suppress_exception=True)
if total < 1:
# if no entries are found, then the plugin has not yet been
# queried or that plugin's entries have expired.
# Most of the time, this will be a no-op for plugins.
self.update_ca_info(plugin)
self.update_ca_info(plugin, session=session)
updates_made = True
if updates_made:
session.flush()
session.commit()
def update_ca_info(self, cert_plugin):
def update_ca_info(self, cert_plugin, session=None):
"""Update the CA info for a particular plugin."""
plugin_name = utils.generate_fullname_for(cert_plugin)
@ -642,18 +649,20 @@ class CertificatePluginManager(named.NamedExtensionManager):
old_cas, offset, limit, total = self.ca_repo.get_by_create_date(
plugin_name=plugin_name,
suppress_exception=True,
session=session,
show_expired=True)
for old_ca in old_cas:
plugin_ca_id = old_ca.plugin_ca_id
if plugin_ca_id not in new_ca_infos.keys():
# remove CAs that no longer exist
self._delete_ca(old_ca)
self._delete_ca(old_ca, session=session)
else:
# update those that still exist
self.ca_repo.update_entity(
old_ca,
new_ca_infos[plugin_ca_id])
new_ca_infos[plugin_ca_id],
session=session)
old_ids = set([ca.plugin_ca_id for ca in old_cas])
new_ids = set(new_ca_infos.keys())
@ -661,17 +670,18 @@ class CertificatePluginManager(named.NamedExtensionManager):
# add new CAs
add_ids = new_ids - old_ids
for add_id in add_ids:
self._add_ca(plugin_name, add_id, new_ca_infos[add_id])
self._add_ca(plugin_name, add_id, new_ca_infos[add_id],
session=session)
def _add_ca(self, plugin_name, plugin_ca_id, ca_info):
def _add_ca(self, plugin_name, plugin_ca_id, ca_info, session=None):
parsed_ca = dict(ca_info)
parsed_ca['plugin_name'] = plugin_name
parsed_ca['plugin_ca_id'] = plugin_ca_id
new_ca = models.CertificateAuthority(parsed_ca)
self.ca_repo.create_from(new_ca)
self.ca_repo.create_from(new_ca, session=session)
def _delete_ca(self, ca):
self.ca_repo.delete_entity_by_id(ca.id, None)
def _delete_ca(self, ca, session=None):
self.ca_repo.delete_entity_by_id(ca.id, None, session=session)
class _CertificateEventPluginManager(named.NamedExtensionManager,

View File

@ -65,6 +65,11 @@ ORDER_STATUS_CA_UNAVAIL_FOR_CHECK = models.OrderStatus(
)
def refresh_certificate_resources():
# Before CA operations can be performed, the CA table must be populated
cert.CertificatePluginManager().refresh_ca_table()
def issue_certificate_request(order_model, project_model, result_follow_on):
"""Create the initial order with CA.

View File

@ -59,9 +59,11 @@ class WhenTestingCAsResource(utils.BarbicanAPIBaseTestCase):
def test_response_should_include_total(self):
self.create_cas()
self.params['plugin_name'] = self.plugin_name
resp = self.app.get('/cas/', self.params)
self.assertIn('total', resp.namespace)
self.assertEqual(self.num_cas, resp.namespace['total'])
self.assertEqual(self.num_cas,
resp.namespace['total'])
def test_should_get_list_certificate_authorities_with_params(self):
self.create_cas()
@ -76,7 +78,7 @@ class WhenTestingCAsResource(utils.BarbicanAPIBaseTestCase):
self.assertEqual(resp.namespace['total'], 1)
def test_should_handle_no_cas(self):
self.params = {'offset': 0, 'limit': 2}
self.params = {'offset': 0, 'limit': 2, 'plugin_name': 'dummy'}
resp = self.app.get('/cas/', self.params)
self.assertEqual(resp.namespace.get('cas'), [])
self.assertEqual(resp.namespace.get('total'), 0)
@ -357,6 +359,7 @@ class WhenTestingCAsResource(utils.BarbicanAPIBaseTestCase):
self.plugin_ca_id = 'default_plugin_ca_id_'
self.ca_id = "id1"
self.num_root_cas = 2
self.num_cas = 10
self.offset = 2
self.limit = 4
@ -415,7 +418,7 @@ class WhenTestingCAsResource(utils.BarbicanAPIBaseTestCase):
# create subca for DELETE testing
parsed_ca = {
'plugin_name': self.plugin_name,
'plugin_name': self.plugin_name + '_delete_me',
'plugin_ca_id': self.plugin_ca_id + "subca 1",
'name': self.plugin_name,
'description': 'Sub CA for default plugin',
@ -429,8 +432,6 @@ class WhenTestingCAsResource(utils.BarbicanAPIBaseTestCase):
ca_repo.save(ca)
self.subca = ca
self.num_cas += 1
def _create_url(self, external_project_id, offset_arg=None,
limit_arg=None):
if limit_arg:

View File

@ -281,9 +281,11 @@ class WhenTestingCertificatePluginManager(utils.BaseTestCase,
self.plugin_returned.get_ca_info.assert_called_once_with()
self.ca_repo.update_entity.assert_called_once_with(
ca1,
ca1_modified_info)
ca1_modified_info,
session=mock.ANY)
self.ca_repo.delete_entity_by_id.assert_called_once_with(
ca2.id,
None)
None,
session=mock.ANY)
self.ca_repo.create_from.assert_has_calls([])

View File

@ -44,16 +44,6 @@ This should provide a response like the following:
{"cas": ["http://localhost:9311/v1/cas/3a2a533d-ed4d-4c68-a418-2ee79f4c9581"], "total": 1}
Note: The list of available CAs is currently populated by the plugins the first
time a certificate order is initiated. At that time, each plugin is queried
for details for each CA with which it is connected. These details have an
expiration time set by the plugin, after which the CA data is requested anew
from the plugin.
This means of course that the CA list is empty until the first certificate
order is processed. You can order a certificate using instructions in
:doc:`Certificates Quick Start <./certificates>`.
.. _getting_ca_details:
Getting Details about a CA

View File

@ -94,10 +94,6 @@ class CATestCommon(base.TestCase):
self.simple_cmc_data = copy.deepcopy(order_simple_cmc_request_data)
# we need to prime the pump ie. populate the CA table by sending
# in an order (just in case)
self.send_test_order()
def tearDown(self):
self.order_behaviors.delete_all_created_orders()
self.ca_behaviors.delete_all_created_cas()

View File

@ -13,12 +13,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import base64
import testtools
from barbican.common import hrefs
from barbican.plugin.interface import certificate_manager as cert_interface
from barbican.tests import certificate_utils as certutil
from functionaltests.api import base
from functionaltests.api.v1.behaviors import ca_behaviors
@ -284,24 +281,7 @@ class QuotaEnforcementTestCase(base.TestCase):
}
}
def send_test_order(self, ca_ref=None):
if self.test_order_sent:
return
self.test_order_sent = True
test_model = order_models.OrderModel(
**self.get_order_simple_cmc_request_data())
test_model.meta['request_data'] = base64.b64encode(
certutil.create_good_csr())
if ca_ref is not None:
ca_id = hrefs.get_ca_id_from_ref(ca_ref)
test_model.meta['ca_id'] = ca_id
create_resp, order_ref = self.order_behaviors.create_order(test_model)
self.assertEqual(202, create_resp.status_code)
self.assertIsNotNone(order_ref)
def get_root_ca_ref(self):
self.send_test_order()
if self.root_ca_ref is not None:
return self.root_ca_ref