1
# vim: tabstop=4 shiftwidth=4 softtabstop=4
3
# Copyright 2010 United States Government as represented by the
4
# Administrator of the National Aeronautics and Space Administration.
7
# Licensed under the Apache License, Version 2.0 (the "License"); you may
8
# not use this file except in compliance with the License. You may obtain
9
# a copy of the License at
11
# http://www.apache.org/licenses/LICENSE-2.0
13
# Unless required by applicable law or agreed to in writing, software
14
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16
# License for the specific language governing permissions and limitations
19
# PORTIONS OF THIS FILE ARE FROM:
20
# http://code.google.com/p/boto
21
# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/
23
# Permission is hereby granted, free of charge, to any person obtaining a
24
# copy of this software and associated documentation files (the
25
# "Software"), to deal in the Software without restriction, including
26
# without limitation the rights to use, copy, modify, merge, publish, dis-
27
# tribute, sublicense, and/or sell copies of the Software, and to permit
28
# persons to whom the Software is furnished to do so, subject to the fol-
31
# The above copyright notice and this permission notice shall be included
32
# in all copies or substantial portions of the Software.
34
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
35
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
36
# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
37
# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
38
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
39
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
43
Utility class for parsing signed AMI manifests.
53
LOG = logging.getLogger('keystone.signer')
57
"""Hacked up code from boto/connection.py"""
59
def __init__(self, secret_key):
60
secret_key = secret_key.encode()
61
self.hmac = hmac.new(secret_key, digestmod=hashlib.sha1)
63
self.hmac_256 = hmac.new(secret_key, digestmod=hashlib.sha256)
65
def generate(self, credentials):
66
"""Generate auth string according to what SignatureVersion is given."""
67
if credentials.params['SignatureVersion'] == '0':
68
return self._calc_signature_0(credentials.params)
69
if credentials.params['SignatureVersion'] == '1':
70
return self._calc_signature_1(credentials.params)
71
if credentials.params['SignatureVersion'] == '2':
72
return self._calc_signature_2(credentials.params,
76
raise Exception('Unknown Signature Version: %s' %
77
credentials.params['SignatureVersion'])
80
def _get_utf8_value(value):
81
"""Get the UTF8-encoded version of a value."""
82
if not isinstance(value, str) and not isinstance(value, unicode):
84
if isinstance(value, unicode):
85
return value.encode('utf-8')
89
def _calc_signature_0(self, params):
90
"""Generate AWS signature version 0 string."""
91
s = params['Action'] + params['Timestamp']
93
return base64.b64encode(self.hmac.digest())
95
def _calc_signature_1(self, params):
96
"""Generate AWS signature version 1 string."""
98
keys.sort(cmp=lambda x, y: cmp(x.lower(), y.lower()))
100
self.hmac.update(key)
101
val = self._get_utf8_value(params[key])
102
self.hmac.update(val)
103
return base64.b64encode(self.hmac.digest())
105
def _calc_signature_2(self, params, verb, server_string, path):
106
"""Generate AWS signature version 2 string."""
107
LOG.debug('using _calc_signature_2')
108
string_to_sign = '%s\n%s\n%s\n' % (verb, server_string, path)
110
current_hmac = self.hmac_256
111
params['SignatureMethod'] = 'HmacSHA256'
113
current_hmac = self.hmac
114
params['SignatureMethod'] = 'HmacSHA1'
119
val = self._get_utf8_value(params[key])
120
val = urllib.quote(val, safe='-_~')
121
pairs.append(urllib.quote(key, safe='') + '=' + val)
123
LOG.debug('query string: %s', qs)
125
LOG.debug('string_to_sign: %s', string_to_sign)
126
current_hmac.update(string_to_sign)
127
b64 = base64.b64encode(current_hmac.digest())
128
LOG.debug('len(b64)=%d', len(b64))
129
LOG.debug('base64 encoded digest: %s', b64)
133
if __name__ == '__main__':
134
print Signer('foo').generate({'SignatureMethod': 'HmacSHA256',
135
'SignatureVersion': '2'},
136
'get', 'server', '/foo')