Verify domain before requesting property updates

Verify that the domain still has a certificate and still
exists on a service. If the domain is found on a service,
verify that it still has the proper protocol and cert type.

Change-Id: If786a91f7a9434468ca5293874b1118f96cf94d6
This commit is contained in:
Isaac Mungai 2016-08-25 10:01:31 -04:00
parent c6317189ca
commit 8c94600fad
2 changed files with 205 additions and 4 deletions

View File

@ -18,6 +18,7 @@ import json
from oslo_log import log
from poppy.manager import base
from poppy.model import ssl_certificate
from poppy.notification.mailgun import driver as n_driver
from poppy.provider.akamai.background_jobs.check_cert_status_and_update \
import check_cert_status_and_update_flow
@ -40,6 +41,8 @@ class BackgroundJobController(base.BackgroundJobController):
a_driver.AKAMAI_GROUP].san_cert_cnames
self.notify_email_list = self.driver.conf[
n_driver.MAIL_NOTIFICATION_GROUP].recipients
self.cert_storage = self._driver.storage.certificates_controller
self.service_storage = self._driver.storage.services_controller
def post_job(self, job_type, kwargs):
queue_data = []
@ -121,7 +124,58 @@ class BackgroundJobController(base.BackgroundJobController):
cert_dict = dict()
try:
cert_dict = json.loads(cert)
# add validation that the domain still exists on a
# service and that it has a type of SAN
cert_obj = ssl_certificate.SSLCertificate(
cert_dict['flavor_id'],
cert_dict['domain_name'],
'san',
project_id=cert_dict['project_id']
)
cert_for_domain = self.cert_storage.get_certs_by_domain(
cert_obj.domain_name,
project_id=cert_obj.project_id,
flavor_id=cert_obj.flavor_id,
cert_type=cert_obj.cert_type
)
if cert_for_domain == []:
ignore_list.append(cert_dict)
LOG.info(
"Ignored property update because "
"certificate for {0} does not exist.".format(
cert_obj.domain_name
)
)
continue
service_obj = self.service_storage.\
get_service_details_by_domain_name(
cert_obj.domain_name,
cert_obj.project_id
)
found = False
for domain in service_obj.domains:
if (
domain.domain == cert_obj.domain_name and
domain.protocol == 'https' and
domain.certificate == 'san'
):
found = True
if found is False:
# skip the task for current cert obj is the
# domain doesn't exist on a service with the
# same protocol and certificate.
ignore_list.append(cert_dict)
LOG.info(
"Ignored update property for a "
"domain '{0}' that no longer exists on a service "
"with the same protocol 'https' and certificate "
"type 'san'".format(
cert_obj.domain_name,
)
)
continue
domain_name = cert_dict["domain_name"]
san_cert = (
cert_dict["cert_details"]
@ -182,9 +236,20 @@ class BackgroundJobController(base.BackgroundJobController):
"notify_email_list": self.notify_email_list
}
self.distributed_task_controller.submit_task(
update_property_flow.update_property_flow,
**t_kwargs)
# check to see if there are changes to be made before submitting
# the task, avoids creating a new property version when there are
# no changes to be made.
if len(cname_host_info_list) > 0:
self.distributed_task_controller.submit_task(
update_property_flow.update_property_flow,
**t_kwargs)
else:
LOG.info(
"No tasks submitted to update_property_flow"
"update_info_list was empty: {0}".format(
update_info_list
)
)
return run_list, ignore_list
else:

View File

@ -21,6 +21,8 @@ from oslo_config import cfg
from poppy.manager.default import background_job
from poppy.manager.default import driver
from poppy.model.helpers import domain
from poppy.model import service
from poppy.notification.mailgun import driver as n_driver
from poppy.provider.akamai import driver as aka_driver
from tests.unit import base
@ -89,6 +91,7 @@ class DefaultSSLCertificateControllerTests(base.TestCase):
def provider_membership(key):
return True if key in self.provider_mocks else False
self.mock_storage = mock_storage
self.mock_providers = mock.MagicMock()
self.mock_providers.__getitem__.side_effect = get_provider_by_name
self.mock_providers.__contains__.side_effect = provider_membership
@ -220,6 +223,29 @@ class DefaultSSLCertificateControllerTests(base.TestCase):
"akamai_update_papi_property_for_mod_san"
)
def test_post_job_positive(self, job_type):
# mock ssl storage returning a cert
self.mock_storage.certificates_controller.\
get_certs_by_domain.return_value = [
mock.Mock()
]
# mock service storage returning a service with domain with
# correct protocol + cert
self.mock_storage.services_controller. \
get_service_details_by_domain_name.return_value = service.Service(
'service_id',
'name',
[
domain.Domain(
"www.example.com",
protocol='https',
certificate='san'
)
],
[],
'flavor_id',
project_id='project_id'
)
san_mapping_queue = self.manager_driver.providers[
'akamai'].obj.san_mapping_queue
san_mapping_queue.traverse_queue.return_value = [
@ -252,8 +278,118 @@ class DefaultSSLCertificateControllerTests(base.TestCase):
self.bgc.distributed_task_controller.submit_task.called
)
def test_post_job_ignored_cert_no_longer_exists(self):
self.mock_storage.certificates_controller.\
get_certs_by_domain.return_value = []
san_mapping_queue = self.manager_driver.providers[
'akamai'].obj.san_mapping_queue
san_mapping_queue.traverse_queue.return_value = [
json.dumps({
"domain_name": "www.example.com",
"flavor_id": "flavor_id",
"project_id": "project_id",
"cert_type": "san",
"cert_details": {
"Akamai": {
"extra_info": {
"san cert": "san.example.com",
"akamai_spsId": 1
}
}
},
'property_activated': True
})
]
run_list, ignore_list = self.bgc.post_job(
"akamai_update_papi_property_for_mod_san",
{'project_id': 'project_id'}
)
self.assertEqual(0, len(run_list))
self.assertEqual(1, len(ignore_list))
self.assertEqual(
False,
self.bgc.distributed_task_controller.submit_task.called
)
def test_post_job_domain_type_modified_on_service(self):
self.mock_storage.certificates_controller.\
get_certs_by_domain.return_value = [
mock.Mock()
]
# simulate domain being changed from https+san to http
self.mock_storage.services_controller. \
get_service_details_by_domain_name.return_value = service.Service(
'service_id',
'name',
[
domain.Domain(
"www.example.com",
protocol='http',
)
],
[],
'flavor_id',
project_id='project_id'
)
san_mapping_queue = self.manager_driver.providers[
'akamai'].obj.san_mapping_queue
san_mapping_queue.traverse_queue.return_value = [
json.dumps({
"domain_name": "www.example.com",
"flavor_id": "flavor_id",
"project_id": "project_id",
"cert_type": "san",
"cert_details": {
"Akamai": {
"extra_info": {
"san cert": "san.example.com",
"akamai_spsId": 1
}
}
},
'property_activated': True
})
]
run_list, ignore_list = self.bgc.post_job(
"akamai_update_papi_property_for_mod_san",
{'project_id': 'project_id'}
)
self.assertEqual(0, len(run_list))
self.assertEqual(1, len(ignore_list))
self.assertEqual(
False,
self.bgc.distributed_task_controller.submit_task.called
)
@ddt.data("akamai_update_papi_property_for_mod_san")
def test_post_job_invalid_san_cert_cname(self, job_type):
# mock ssl storage returning a cert
self.mock_storage.certificates_controller.\
get_certs_by_domain.return_value = [
mock.Mock()
]
# mock service storage returning a service with domain with
# correct protocol + cert
self.mock_storage.services_controller. \
get_service_details_by_domain_name.return_value = service.Service(
'service_id',
'name',
[
domain.Domain(
"www.example.com",
protocol='https',
certificate='san'
)
],
[],
'flavor_id',
project_id='project_id'
)
san_mapping_queue = self.manager_driver.providers[
'akamai'].obj.san_mapping_queue
san_mapping_queue.traverse_queue.return_value = [
@ -281,7 +417,7 @@ class DefaultSSLCertificateControllerTests(base.TestCase):
self.assertEqual(1, len(ignore_list))
self.assertEqual(
True,
False,
self.bgc.distributed_task_controller.submit_task.called
)