1
# Copyright [2010] [Anso Labs, LLC]
3
# Licensed under the Apache License, Version 2.0 (the "License");
4
# you may not use this file except in compliance with the License.
5
# You may obtain a copy of the License at
7
# http://www.apache.org/licenses/LICENSE-2.0
9
# Unless required by applicable law or agreed to in writing, software
10
# distributed under the License is distributed on an "AS IS" BASIS,
11
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
# See the License for the specific language governing permissions and
13
# limitations under the License.
15
# PORTIONS OF THIS FILE ARE FROM:
16
# http://code.google.com/p/boto
17
# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/
19
# Permission is hereby granted, free of charge, to any person obtaining a
20
# copy of this software and associated documentation files (the
21
# "Software"), to deal in the Software without restriction, including
22
# without limitation the rights to use, copy, modify, merge, publish, dis-
23
# tribute, sublicense, and/or sell copies of the Software, and to permit
24
# persons to whom the Software is furnished to do so, subject to the fol-
27
# The above copyright notice and this permission notice shall be included
28
# in all copies or substantial portions of the Software.
30
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
31
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
32
# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
33
# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
34
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
39
Utility class for parsing signed AMI manifests.
47
from nova.exception import Error
49
_log = logging.getLogger('signer')
50
logging.getLogger('signer').setLevel(logging.WARN)
53
""" hacked up code from boto/connection.py """
55
def __init__(self, secret_key):
56
self.hmac = hmac.new(secret_key, digestmod=hashlib.sha1)
58
self.hmac_256 = hmac.new(secret_key, digestmod=hashlib.sha256)
60
def generate(self, params, verb, server_string, path):
61
if params['SignatureVersion'] == '0':
62
t = self._calc_signature_0(params)
63
elif params['SignatureVersion'] == '1':
64
t = self._calc_signature_1(params)
65
elif params['SignatureVersion'] == '2':
66
t = self._calc_signature_2(params, verb, server_string, path)
68
raise Error('Unknown Signature Version: %s' % self.SignatureVersion)
71
def _get_utf8_value(self, value):
72
if not isinstance(value, str) and not isinstance(value, unicode):
74
if isinstance(value, unicode):
75
return value.encode('utf-8')
79
def _calc_signature_0(self, params):
80
s = params['Action'] + params['Timestamp']
83
keys.sort(cmp = lambda x, y: cmp(x.lower(), y.lower()))
86
val = self._get_utf8_value(params[key])
87
pairs.append(key + '=' + urllib.quote(val))
88
return base64.b64encode(self.hmac.digest())
90
def _calc_signature_1(self, params):
92
keys.sort(cmp = lambda x, y: cmp(x.lower(), y.lower()))
96
val = self._get_utf8_value(params[key])
98
pairs.append(key + '=' + urllib.quote(val))
99
return base64.b64encode(self.hmac.digest())
101
def _calc_signature_2(self, params, verb, server_string, path):
102
_log.debug('using _calc_signature_2')
103
string_to_sign = '%s\n%s\n%s\n' % (verb, server_string, path)
106
params['SignatureMethod'] = 'HmacSHA256'
109
params['SignatureMethod'] = 'HmacSHA1'
114
val = self._get_utf8_value(params[key])
115
pairs.append(urllib.quote(key, safe='') + '=' + urllib.quote(val, safe='-_~'))
117
_log.debug('query string: %s' % qs)
119
_log.debug('string_to_sign: %s' % string_to_sign)
120
hmac.update(string_to_sign)
121
b64 = base64.b64encode(hmac.digest())
122
_log.debug('len(b64)=%d' % len(b64))
123
_log.debug('base64 encoded digest: %s' % b64)
126
if __name__ == '__main__':
127
print Signer('foo').generate({"SignatureMethod": 'HmacSHA256', 'SignatureVersion': '2'}, "get", "server", "/foo")