Skip to content
This repository was archived by the owner on Feb 15, 2022. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion poppy/manager/default/background_job.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,10 @@ def post_job(self, job_type, kwargs):
)
t_kwargs = {
"cert_obj_json": json.dumps(cert_dict),
"project_id": cert_dict.get("project_id")
"project_id": cert_dict.get("project_id"),
"property_spec": kwargs.get(
"property_spec",
'akamai_https_sni_config_numbers')
}
if cert_dict.get('property_activated', False) is True:
self.distributed_task_controller.submit_task(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@

def check_cert_status_and_update_flow():
flow = linear_flow.Flow('Update Akamai Property').add(
check_cert_status_and_update_tasks.GetHostnamesFromProperty(),
check_cert_status_and_update_tasks.GetCertInfoTask(),
check_cert_status_and_update_tasks.CheckCertStatusTask(),
check_cert_status_and_update_tasks.UpdateCertStatusTask()
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,54 @@
conf(project='poppy', prog='poppy', args=[])


class GetHostnamesFromProperty(task.Task):
default_provides = 'hosts_in_latest_property'

def __init__(self):
super(GetHostnamesFromProperty, self).__init__()
service_controller, self.providers = \
memoized_controllers.task_controllers('poppy', 'providers')
self.akamai_driver = self.providers['akamai'].obj
self.existing_hosts = []

def execute(self, property_spec):
"""Get the host names from the latest property"""
self.property_id = self.akamai_driver.papi_property_id(property_spec)

LOG.info('Starting to get latest version for property: %s'
% self.property_id)
resp = self.akamai_driver.akamai_papi_api_client.get(
self.akamai_driver.akamai_papi_api_base_url.format(
middle_part='properties/%s' % self.property_id)
)
if resp.status_code != 200:
raise RuntimeError('PAPI API request failed.'
'Exception: %s' % resp.text)
else:
property = json.loads(resp.text)['properties']['items'][0]
latestVersion = property['latestVersion'] or 0
production_version = property['productionVersion'] or -1
staging_version = property['stagingVersion'] or -1

max_version = max(latestVersion, production_version,
staging_version)
resp = self.akamai_driver.akamai_papi_api_client.get(
self.akamai_driver.akamai_papi_api_base_url.format(
middle_part='properties/%s/versions/%s/hostnames' %
(self.property_id,
str(max_version)))
)
if resp.status_code != 200:
raise RuntimeError('PAPI API request failed.'
'Exception: %s' % resp.text)
self.existing_hosts = json.loads(resp.text)['hostnames'][
'items']
self.existing_hosts = [str(host['cnameFrom'])
for host in self.existing_hosts]

return self.existing_hosts


class GetCertInfoTask(task.Task):
default_provides = "cert_obj_json"

Expand Down Expand Up @@ -55,7 +103,7 @@ def __init__(self):
memoized_controllers.task_controllers('poppy', 'providers')
self.akamai_driver = self.providers['akamai'].obj

def execute(self, cert_obj_json):
def execute(self, cert_obj_json, hosts_in_latest_property):
if cert_obj_json != "":
cert_obj = ssl_certificate.load_from_json(
json.loads(cert_obj_json))
Expand Down Expand Up @@ -156,7 +204,16 @@ def execute(self, cert_obj_json):

if change_url not in pending_changes:
if cert_obj.domain_name in dns_names:
return "deployed"
if cert_obj.domain_name in hosts_in_latest_property:
return "deployed"
else:
# The hostname is still not on the latest
# property version. Return the item to the
# queue. Another attempt to update property
# should happen.
self.akamai_driver.san_mapping_queue.enqueue_san_mapping(
json.dumps(cert_obj.to_dict()))
return current_status
else:
return "failed"
else:
Expand Down Expand Up @@ -214,4 +271,4 @@ def execute(self, project_id, cert_obj_json, status_change_to):
service_obj.provider_details
)
else:
pass
pass
89 changes: 89 additions & 0 deletions tests/unit/provider/akamai/background_jobs/akamai_mocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,18 @@ def get_providers():
}
akamai_mock_provider_obj.akamai_sps_api_client = MockSPSAPIClient()
akamai_mock_provider_obj.akamai_papi_api_client = MockPapiAPIClient()
akamai_mock_provider_obj.akamai_cps_api_client = MockCPSAPIClient()
akamai_mock_provider_obj.akamai_sps_api_base_url = (
'https://mybaseurl.net/config-secure-provisioning-service/'
'v1/sps-requests/{spsId}?'
'contractId=None&groupId=None')
akamai_mock_provider_obj.akamai_papi_api_base_url = (
'https://mybaseurl.net/papi/v1/{middle_part}/'
'?contractId=ctr_None&groupId=grp_None')
akamai_mock_provider_obj.akamai_cps_api_base_url = (
'https://mybaseurl.net/'
'/cps/v2/enrollments/{enrollmentId}'
)
akamai_mock_provider_obj.san_mapping_queue.\
traverse_queue.return_value = []
akamai_mock_provider.obj = akamai_mock_provider_obj
Expand Down Expand Up @@ -108,6 +113,26 @@ def get_certs_by_domain(self, domain_name, project_id=None,
flavor_id=None,
cert_type=None):

if cert_type == 'sni':
return ssl_certificate.SSLCertificate(
"premium",
"blog.testabcd.com",
"sni",
project_id=project_id,
cert_details={
'Akamai': {
u'cert_domain': u'secure2.san1.test_123.com',
u'extra_info': {
u'change_url': '/cps/v2/enrollments/10000/changes/10000',
u'action': u'Waiting for customer domain '
'validation for blog.testabc.com',
u'create_at': u'2015-09-29 16:09:12.429147',
u'san cert': u'secure2.san1.test_123.com',
u'status': u'create_in_progress'}
}
}
)

return ssl_certificate.SSLCertificate(
"premium",
"blog.testabcd.com",
Expand Down Expand Up @@ -165,6 +190,11 @@ def get(self, url):
"edgeHostnameId": "ehn_1126816",
"cnameFrom": "secure.san2.test_789.com",
"cnameTo": "secure.test_456.com.edge_host_test.net"
}, {
"cnameType": "EDGE_HOSTNAME",
"edgeHostnameId": "ehn_1231234",
"cnameFrom": "blog.testabcd.com",
"cnameTo": "secure.test_456.com.edge_host_test.net"
}]
}
})
Expand Down Expand Up @@ -341,3 +371,62 @@ def post(self, url, data=None, headers=None):

def put(self, url, data=None, headers=None):
return self.response_200

class MockCPSAPIClient(mock.Mock):
def __init__(self):
super(MockCPSAPIClient, self).__init__()
self.response_200 = mock.Mock(status_code=200)

def get(self, url, headers):
self.response_200.text = json.dumps({
"location": "/cps/v2/enrollments/10002",
"ra": "third-party",
"validationType": "third-party",
"certificateType": "third-party",
"certificateChainType": "default",
"networkConfiguration": {
"geography": "core",
"secureNetwork": "enhanced-tls",
"mustHaveCiphers": "ak-akamai-default",
"preferredCiphers": "ak-akamai-default-interim",
"disallowedTlsVersions": [],
"sniOnly": True,
"quicEnabled": False,
"sni": {
"cloneDnsNames": False,
"dnsNames": [
"blog.testabcd.com",
"san1.example.com"
]
},
"ocspStapling": "not-set"
},
"signatureAlgorithm": None,
"changeManagement": True,
"csr": {
"cn": "www.example.com",
"c": "US",
"st": "MA",
"l": "Cambridge",
"o": "Akamai",
"ou": "WebEx",
"sans": [
"san1.example.com",
"san2.example.com",
"san3.example.com"
]
},

"thirdParty": {
"excludeSans": False
},
"enableMultiStackedCertificates": False,
"pendingChanges": [
"/cps/v2/enrollments/10002/changes/10002"
],
"maxAllowedSanNames": 100,
"maxAllowedWildcardSanNames": 100
})

self.response_200.status_code = 200
return self.response_200
34 changes: 17 additions & 17 deletions tests/unit/provider/akamai/background_jobs/test_flows.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,24 +72,12 @@ def task_controllers_side_effect(*args, **kwargs):
self.addCleanup(bootstrap_patcher.stop)

def test_check_cert_status_and_update_flow(self):
cert_obj_json = json.dumps(
ssl_certificate.SSLCertificate(
'cdn',
'website.com',
'san',
cert_details={
'Akamai': {
'extra_info': {
'san cert': 'secure1.san1.testcdn.com'
}
}
}
).to_dict()
)

kwargs = {
'cert_obj_json': cert_obj_json,
'project_id': "000"
'domain_name': 'website.com',
'cert_type': 'san',
'flavor_id': 'cdn',
'project_id': "000",
"property_spec": "akamai_https_san_config_numbers"
}
engines.run(check_cert_status_and_update_flow.
check_cert_status_and_update_flow(),
Expand All @@ -115,3 +103,15 @@ def test_update_papi_flow(self):
}
engines.run(update_property_flow.update_property_flow(),
store=kwargs)

def test_domain_exists_in_latest_property_hostnames(self):
kwargs = {
'domain_name': 'website.com',
'cert_type': 'sni',
'flavor_id': 'flavor1',
'project_id': "000",
"property_spec": "akamai_https_san_config_numbers"
}
engines.run(check_cert_status_and_update_flow.
check_cert_status_and_update_flow(),
store=kwargs)