OpenStack Orchestration (Heat)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

125 lines
4.4 KiB

# 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
# 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.
from keystoneclient.contrib.ec2 import utils as ec2_utils
from oslo_config import cfg
from oslo_log import log as logging
from six.moves.urllib import parse as urlparse
from heat.common.i18n import _LW
from heat.engine.resources import stack_user
LOG = logging.getLogger(__name__)
) = (
'/waitcondition', '/signal'
class SignalResponder(stack_user.StackUser):
# Anything which subclasses this may trigger authenticated
# API operations as a consequence of handling a signal
requires_deferred_auth = True
def handle_create(self):
super(SignalResponder, self).handle_create()
def handle_delete(self):
super(SignalResponder, self).handle_delete()
def _delete_ec2_signed_url(self):
def _get_ec2_signed_url(self, signal_type=SIGNAL):
"""Create properly formatted and pre-signed URL.
This uses the created user for the credentials.
See boto/
:param signal_type: either WAITCONDITION or SIGNAL.
stored ='ec2_signed_url')
if stored is not None:
return stored
access_key ='access_key')
secret_key ='secret_key')
if not access_key or not secret_key:
LOG.warn(_LW('Cannot generate signed url, '
'no stored access/secret key'))
config_url = cfg.CONF.heat_waitcondition_server_url
if config_url:
signal_url = config_url.replace('/waitcondition', signal_type)
heat_client_plugin = self.stack.clients.client_plugin('heat')
endpoint = heat_client_plugin.get_heat_cfn_url()
signal_url = ''.join([endpoint, signal_type])
host_url = urlparse.urlparse(signal_url)
path = self.identifier().arn_url_path()
# Note the WSGI spec apparently means that the webob request we end up
# processing in the CFN API ( has an unquoted path, so we
# need to calculate the signature with the path component unquoted, but
# ensure the actual URL contains the quoted version...
unquoted_path = urlparse.unquote(host_url.path + path)
request = {'host': host_url.netloc.lower(),
'verb': SIGNAL_VERB[signal_type],
'path': unquoted_path,
'params': {'SignatureMethod': 'HmacSHA256',
'SignatureVersion': '2',
'AWSAccessKeyId': access_key,
# Sign the request
signer = ec2_utils.Ec2Signer(secret_key)
request['params']['Signature'] = signer.generate(request)
qs = urlparse.urlencode(request['params'])
url = "%s%s?%s" % (signal_url.lower(),
path, qs)
self.data_set('ec2_signed_url', url)
return url
def _delete_heat_signal_url(self):
def _get_heat_signal_url(self):
stored ='heat_signal_url')
if stored is not None:
return stored
url = self.client_plugin('heat').get_heat_url()
host_url = urlparse.urlparse(url)
path = self.identifier().url_path()
url = urlparse.urlunsplit(
(host_url.scheme, host_url.netloc, 'v1/%s/signal' % path, '', ''))
self.data_set('heat_signal_url', url)
return url