From d0e44ded0a07cfe6b3413693d79c7f1f67b27701 Mon Sep 17 00:00:00 2001 From: Rabi Mishra Date: Fri, 5 Jun 2020 23:30:09 +0530 Subject: [PATCH] Use never expiring alarm_url for resource attributes Don't use timestamp when generating ec2 signed url for alarm url attributes of resource. This will resolve the issue for new resources even if they are cached in attributes or resource_data. However, for existing stacks containing these resources the current best option is to not cache these attributes and allow alarm resources to be able to get a new never expiring urls in the next forced update. Change-Id: If2ebc3deacb770294004ae023500367af603b59e Task: 39985 Related-Bug: #1872737 --- .../resources/aws/autoscaling/scaling_policy.py | 5 +++-- .../resources/openstack/heat/scaling_policy.py | 5 +++-- .../resources/openstack/mistral/workflow.py | 5 +++-- heat/engine/resources/openstack/sahara/job.py | 5 +++-- heat/engine/resources/signal_responder.py | 16 +++++++++------- .../autoscaling/test_heat_scaling_policy.py | 1 - 6 files changed, 21 insertions(+), 16 deletions(-) diff --git a/heat/engine/resources/aws/autoscaling/scaling_policy.py b/heat/engine/resources/aws/autoscaling/scaling_policy.py index b87890dfd4..c4310fe265 100644 --- a/heat/engine/resources/aws/autoscaling/scaling_policy.py +++ b/heat/engine/resources/aws/autoscaling/scaling_policy.py @@ -83,7 +83,8 @@ class AWSScalingPolicy(heat_sp.AutoScalingPolicy): attributes_schema = { ALARM_URL: attributes.Schema( _("A signed url to handle the alarm. (Heat extension)."), - type=attributes.Schema.STRING + type=attributes.Schema.STRING, + cache_mode=attributes.Schema.CACHE_NONE ), } @@ -99,7 +100,7 @@ class AWSScalingPolicy(heat_sp.AutoScalingPolicy): def get_reference_id(self): if self.resource_id is not None: - return str(self._get_ec2_signed_url()) + return str(self._get_ec2_signed_url(never_expire=True)) else: return str(self.name) diff --git a/heat/engine/resources/openstack/heat/scaling_policy.py b/heat/engine/resources/openstack/heat/scaling_policy.py index cc06227104..8ca88275f3 100644 --- a/heat/engine/resources/openstack/heat/scaling_policy.py +++ b/heat/engine/resources/openstack/heat/scaling_policy.py @@ -98,7 +98,8 @@ class AutoScalingPolicy(signal_responder.SignalResponder): attributes_schema = { ALARM_URL: attributes.Schema( _("A signed url to handle the alarm."), - type=attributes.Schema.STRING + type=attributes.Schema.STRING, + cache_mode=attributes.Schema.CACHE_NONE ), SIGNAL_URL: attributes.Schema( _("A url to handle the alarm using native API."), @@ -185,7 +186,7 @@ class AutoScalingPolicy(signal_responder.SignalResponder): if self.resource_id is None: return if name == self.ALARM_URL: - return str(self._get_ec2_signed_url()) + return str(self._get_ec2_signed_url(never_expire=True)) elif name == self.SIGNAL_URL: return str(self._get_heat_signal_url()) diff --git a/heat/engine/resources/openstack/mistral/workflow.py b/heat/engine/resources/openstack/mistral/workflow.py index 63c0d204fd..c9113faa9b 100644 --- a/heat/engine/resources/openstack/mistral/workflow.py +++ b/heat/engine/resources/openstack/mistral/workflow.py @@ -375,7 +375,8 @@ class Workflow(signal_responder.SignalResponder, ALARM_URL: attributes.Schema( _("A signed url to create executions for workflows specified in " "Workflow resource."), - type=attributes.Schema.STRING + type=attributes.Schema.STRING, + cache_mode=attributes.Schema.CACHE_NONE ), EXECUTIONS: attributes.Schema( _("List of workflows' executions, each of them is a dictionary " @@ -660,7 +661,7 @@ class Workflow(signal_responder.SignalResponder, self.INPUT: self.properties.get(self.INPUT)} elif name == self.ALARM_URL and self.resource_id is not None: - return str(self._get_ec2_signed_url()) + return str(self._get_ec2_signed_url(never_expire=True)) def resource_mapping(): diff --git a/heat/engine/resources/openstack/sahara/job.py b/heat/engine/resources/openstack/sahara/job.py index 4b3c8009a0..cda967946b 100644 --- a/heat/engine/resources/openstack/sahara/job.py +++ b/heat/engine/resources/openstack/sahara/job.py @@ -180,7 +180,8 @@ class SaharaJob(signal_responder.SignalResponder, resource.Resource): DEFAULT_EXECUTION_URL: attributes.Schema( _("A signed url to create execution specified in " "default_execution_data property."), - type=attributes.Schema.STRING + type=attributes.Schema.STRING, + cache_mode=attributes.Schema.CACHE_NONE ), EXECUTIONS: attributes.Schema( _("List of the job executions."), @@ -296,7 +297,7 @@ class SaharaJob(signal_responder.SignalResponder, resource.Resource): def _resolve_attribute(self, name): if name == self.DEFAULT_EXECUTION_URL: - return str(self._get_ec2_signed_url()) + return str(self._get_ec2_signed_url(never_expire=True)) elif name == self.EXECUTIONS: try: job_execs = self.client().job_executions.find( diff --git a/heat/engine/resources/signal_responder.py b/heat/engine/resources/signal_responder.py index a7aa180d5b..d23730f6f5 100644 --- a/heat/engine/resources/signal_responder.py +++ b/heat/engine/resources/signal_responder.py @@ -116,7 +116,8 @@ class SignalResponder(stack_user.StackUser): 'domain_id': self.keystone().stack_domain_id, 'region_name': self._get_region_name()} - def _get_ec2_signed_url(self, signal_type=SIGNAL): + def _get_ec2_signed_url(self, signal_type=SIGNAL, + never_expire=False): """Create properly formatted and pre-signed URL. This uses the created user for the credentials. @@ -160,15 +161,16 @@ class SignalResponder(stack_user.StackUser): # need to calculate the signature with the path component unquoted, but # ensure the actual URL contains the quoted version... unquoted_path = parse.unquote(host_url.path + path) + params = {'SignatureMethod': 'HmacSHA256', + 'SignatureVersion': '2', + 'AWSAccessKeyId': access_key} + if not never_expire: + params['Timestamp'] = timeutils.utcnow().strftime( + "%Y-%m-%dT%H:%M:%SZ") request = {'host': host_url.netloc.lower(), 'verb': SIGNAL_VERB[signal_type], 'path': unquoted_path, - 'params': {'SignatureMethod': 'HmacSHA256', - 'SignatureVersion': '2', - 'AWSAccessKeyId': access_key, - 'Timestamp': - timeutils.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ") - }} + 'params': params} # Sign the request signer = ec2_utils.Ec2Signer(secret_key) request['params']['Signature'] = signer.generate(request) diff --git a/heat/tests/autoscaling/test_heat_scaling_policy.py b/heat/tests/autoscaling/test_heat_scaling_policy.py index 1d864c6b32..658426635f 100644 --- a/heat/tests/autoscaling/test_heat_scaling_policy.py +++ b/heat/tests/autoscaling/test_heat_scaling_policy.py @@ -182,7 +182,6 @@ class ScalingPolicyAttrTest(common.HeatTestCase): self.assertEqual('Signature', args[1].split('=')[0]) self.assertEqual('SignatureMethod', args[2].split('=')[0]) self.assertEqual('SignatureVersion', args[3].split('=')[0]) - self.assertEqual('Timestamp', args[4].split('=')[0]) def test_signal_attribute(self): heat_plugin = self.stack.clients.client_plugin('heat')