annotate kcl/ec2.py @ 0:0f44ee073173 default tip

fake salt, initial commit
author Jeff Hammel <k0scist@gmail.com>
date Mon, 06 Feb 2017 01:10:22 +0000
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
1 """
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
2 code for interfacing with EC2 instances:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
3
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
4 curl http://169.254.169.254/latest/meta-data/
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
5 """
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
6
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
7 # imports
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
8 import argparse
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
9 import boto.utils
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
10 import hashlib
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
11 import hmac
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
12 import json
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
13 import os
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
14 import requests
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
15 import sys
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
16 import urllib
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
17 import urlparse
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
18 import ConfigParser
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
19 from collections import OrderedDict
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
20 from datetime import datetime
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
21
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
22
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
23 class FilesystemCredentials(object):
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
24 """
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
25 Read credentials from the filesystem. See:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
26 - http://boto.cloudhackers.com/en/latest/boto_config_tut.html
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
27 - https://blogs.aws.amazon.com/security/post/Tx3D6U6WSFGOK2H/A-New-and-Standardized-Way-to-Manage-Credentials-in-the-AWS-SDKs
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
28
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
29 In Unix/Linux systems, on startup, the boto library looks
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
30 for configuration files in the following locations
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
31 and in the following order:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
32
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
33 /etc/boto.cfg - for site-wide settings that all users on this machine will use
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
34 (if profile is given) ~/.aws/credentials - for credentials shared between SDKs
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
35 (if profile is given) ~/.boto - for user-specific settings
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
36 ~/.aws/credentials - for credentials shared between SDKs
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
37 ~/.boto - for user-specific settings
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
38
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
39 """
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
40
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
41 def read_aws_credentials(self, fp, section='default'):
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
42 parser = ConfigParser.RawConfigParser()
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
43 parser.readfp(fp)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
44 if section in parser.sections():
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
45 key = 'aws_access_key_id'
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
46 if parser.has_option(section, key):
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
47 secret = 'aws_secret_access_key'
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
48 if parser.has_option(section, secret):
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
49 return (parser.get(section, key),
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
50 parser.get(section, secret))
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
51
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
52 def __init__(self):
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
53 self.resolution = OrderedDict()
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
54 home = os.environ['HOME']
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
55 if home:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
56 self.resolution[os.path.join(home, '.aws', 'credentials')] = self.read_aws_credentials
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
57
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
58 def __call__(self):
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
59 """
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
60 return credentials....*if* available
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
61 """
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
62
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
63 for path, method in self.resolution.items():
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
64 if os.path.isfile(path):
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
65 with open(path, 'r') as f:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
66 credentials = method(f)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
67 if credentials:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
68 return credentials
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
69
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
70
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
71 class EC2Metadata(object):
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
72 """EC2 instance metadata interface"""
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
73
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
74 def __init__(self, **kwargs):
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
75 self._kwargs = kwargs
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
76
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
77 def __call__(self):
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
78 """http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html"""
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
79 return boto.utils.get_instance_metadata(**self._kwargs)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
80
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
81 def security_credentials(self):
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
82 """
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
83 return IAM credentials for an instance, if possible
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
84
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
85 See:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
86 http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html#instance-metadata-security-credentials
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
87 """
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
88 # TODO: nested dict -> object notation mapping ;
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
89 # note also this is actually a `LazyLoader` value,
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
90 # not actually a dict
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
91
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
92 return self()['iam']['security-credentials']
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
93
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
94 def credentials(self, role=None):
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
95 """return active credentials"""
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
96
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
97 security_credentials = self.security_credentials()
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
98 if not security_credentials:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
99 raise AssertionError("No security credentials available")
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
100
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
101 roles=', '.join(sorted(security_credentials.keys()))
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
102 if role is None:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
103 if len(security_credentials) > 1:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
104 raise AssertionError("No role given and multiple roles found for instance: {roles}".format(roles))
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
105 role = security_credentials.keys()[0]
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
106
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
107 if role not in security_credentials:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
108 raise KeyError("Role {role} not in available IAM roles: {roles}".format(role=role, roles=roles))
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
109
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
110 return security_credentials[role]
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
111
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
112 class AWSCredentials(FilesystemCredentials):
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
113 """
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
114 try to read credentials from the filesystem
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
115 then from ec2 metadata
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
116 """
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
117
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
118 def __call__(self):
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
119
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
120 # return filesystem crednetials, if any
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
121 credentials = FilesystemCredentials.__call__(self)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
122 if credentials:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
123 return credentials
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
124
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
125 # otherwise try to return credentials from metadata
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
126 metadata = EC2Metadata()
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
127 try:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
128 ec2_credentials = metadata.credentials()
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
129 except AssertionError:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
130 return
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
131 keys = ('AccessKeyId', 'SecretAccessKey')
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
132 if set(keys).issubset(ec2_credentials.keys()):
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
133 return [ec2_credentials[key]
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
134 for key in keys]
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
135
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
136 class SignedRequest(object):
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
137 """
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
138 Signed request using Signature Version 4
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
139
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
140 http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
141 """
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
142
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
143 # signing information:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
144 algorithm = 'AWS4-HMAC-SHA256'
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
145 termination_string = 'aws4_request'
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
146 authorization_header = "{algorithm} Credential={access_key}/{credential_scope}, SignedHeaders={signed_headers}, Signature={signature}"
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
147
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
148 # date format:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
149 date_format = '%Y%m%d'
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
150 time_format = '%H%M%S'
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
151
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
152 ### date methods
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
153
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
154 @classmethod
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
155 def datetime_format(cls):
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
156 return '{date_format}T{time_format}Z'.format(date_format=cls.date_format,
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
157 time_format=cls.time_format)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
158
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
159 @classmethod
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
160 def datetime(cls, _datetime=None):
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
161 """
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
162 returns formatted datetime string as appropriate
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
163 for `x-amz-date` header
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
164 """
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
165
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
166 if _datetime is None:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
167 _datetime = datetime.utcnow()
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
168 return _datetime.strftime(cls.datetime_format())
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
169
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
170 ### constructor
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
171
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
172 def __init__(self, access_key, secret_key, region, service):
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
173 self.access_key = access_key
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
174 self.secret_key = secret_key
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
175 self.region = region
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
176 self.service = service
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
177
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
178 ### hashing methods
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
179
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
180 def hash(self, message):
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
181 """hash a `message`"""
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
182 # from e.g. http://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html#sig-v4-examples-get-auth-header
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
183 return hashlib.sha256(message).hexdigest()
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
184
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
185 def sign(self, key, msg):
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
186 """
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
187 See:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
188 http://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html#signature-v4-examples-python
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
189 """
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
190 return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest()
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
191
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
192 def signature_key(self, date_stamp):
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
193 parts = [date_stamp,
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
194 self.region,
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
195 self.service,
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
196 self.termination_string]
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
197 signed = ('AWS4' + self.secret_key).encode('utf-8')
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
198 while parts:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
199 signed = self.sign(signed, parts.pop(0))
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
200 return signed
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
201
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
202 ###
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
203
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
204 def credential_scope(self, date_string):
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
205 """
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
206 a string that includes the date, the region you are targeting,
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
207 the service you are requesting, and a termination string
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
208 ("aws4_request") in lowercase characters.
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
209 """
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
210
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
211 parts = [date_string,
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
212 self.region,
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
213 self.service,
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
214 self.termination_string]
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
215 # TODO: "The region and service name strings must be UTF-8 encoded."
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
216 return '/'.join(parts)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
217
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
218 ### method for canonical components
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
219
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
220 @classmethod
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
221 def canonical_uri(cls, path):
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
222 """
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
223 The canonical URI is the URI-encoded version
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
224 of the absolute path component of the URI
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
225 """
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
226
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
227 if path == '/':
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
228 path = None
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
229 if path:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
230 canonical_uri = urllib.quote(path, safe='')
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
231 else:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
232 # If the absolute path is empty, use a forward slash (/)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
233 canonical_uri = '/'
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
234 return canonical_uri
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
235
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
236 @classmethod
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
237 def canonical_query(cls, query_string):
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
238 """
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
239 returns the canonical query string
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
240 """
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
241 # TODO: currently this does not use `cls`
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
242
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
243 # split into parameter names + values
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
244 query = urlparse.parse_qs(query_string)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
245
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
246 # make this into a more appropriate data structure for processing
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
247 keyvalues = sum([[[key, value] for value in values]
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
248 for key, values in query.items()], [])
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
249
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
250 # a. URI-encode each parameter name and value
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
251 def encode(string):
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
252 return urllib.quote(string, safe='/')
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
253 encoded = [[encode(string) for string in pair]
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
254 for pair in keyvalues]
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
255
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
256 # b. Sort the encoded parameter names by character code in ascending order (ASCII order)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
257 encoded.sort()
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
258
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
259 # c. Build the canonical query string by starting with the first parameter name in the sorted list.
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
260 # d. For each parameter, append the URI-encoded parameter name, followed by the character '=' (ASCII code 61), followed by the URI-encoded parameter value.
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
261 # e. Append the character '&' (ASCII code 38) after each parameter value, except for the last value in the list.
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
262 retval = '&'.join(['{name}={value}'.format(name=name,
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
263 value=value)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
264 for name, value in encoded])
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
265 return retval
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
266
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
267 @classmethod
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
268 def signed_headers(cls, headers):
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
269 """
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
270 return a list of signed headers
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
271 """
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
272 names = [name.lower() for name in headers.keys()]
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
273 names.sort()
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
274 return ';'.join(names)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
275
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
276 @classmethod
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
277 def canonical_headers(cls, headers):
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
278 """
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
279 return canonical headers:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
280 Construct each header according to the following rules:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
281 * Append the lowercase header name followed by a colon.
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
282 * ...
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
283 See:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
284 - http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
285 - http://docs.python-requests.org/en/latest/user/quickstart/#custom-headers
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
286 """
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
287
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
288 canonical_headers = []
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
289 for key, value in headers.items():
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
290
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
291 # convert header name to lowercase
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
292 key = key.lower()
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
293
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
294 # trim excess white space from the header values
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
295 value = value.strip()
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
296
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
297 # convert sequential spaces in the value to a single space.
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
298 # However, do not remove extra spaces from any values
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
299 # that are inside quotation marks.
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
300 quote = '"'
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
301 if not (value and value[0] == quote and value[-1] == quote):
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
302 value = ' '.join(value.split())
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
303
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
304 canonical_headers.append((key, value))
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
305
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
306 # check for duplicate headers
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
307 names = [name for name, value in canonical_headers]
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
308 if len(set(names)) != len(names):
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
309 raise AssertionError("You have duplicate header names :( While AWS supports this use-case, this library doesn't yet")
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
310 # Append a comma-separated list of values for that header.
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
311 # If there are duplicate headers, the values are comma-separated.
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
312 # Do not sort the values in headers that have multiple values.
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
313
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
314 # Build the canonical headers list by sorting the headers by lowercase character code
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
315 canonical_headers.sort(key=lambda x: x[0])
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
316
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
317 # return canonical headers
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
318 return canonical_headers
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
319
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
320 def __call__(self, url, method='GET', headers=None, session=None):
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
321 """create a signed request and return the response"""
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
322
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
323 if session:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
324 raise NotImplementedError('TODO')
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
325 else:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
326 session = requests.Session()
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
327 signed_request = self.signed_request(url,
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
328 method=method,
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
329 headers=headers)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
330 response = session.send(signed_request)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
331 return response
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
332
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
333 def canonical_request(self, url, headers, payload='', method='GET'):
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
334 """
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
335 Return canonical request
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
336
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
337 url: "http://k0s.org/home/documents and settings"
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
338 GET
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
339 %2Fhome%2Fdocuments%20and%20settings
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
340 ...
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
341 """
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
342
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
343 # parse the url
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
344 parsed = urlparse.urlsplit(url)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
345
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
346 # get canonical URI
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
347 canonical_uri = self.canonical_uri(parsed.path)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
348
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
349 # construct the canonical query string
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
350 canonical_query = self.canonical_query(parsed.query)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
351
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
352 # get the canonical headers
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
353 canonical_headers = self.canonical_headers(headers)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
354
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
355 # format the canonical headers
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
356 canonical_header_string = '\n'.join(['{0}:{1}'.format(*header)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
357 for header in canonical_headers]) + '\n'
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
358
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
359 # get the signed headers
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
360 signed_headers = self.signed_headers(headers)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
361
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
362 # get the hashed payload
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
363 hashed_payload = self.hash(payload)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
364
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
365 # join the parts to make the request:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
366 # http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
367 # CanonicalRequest =
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
368 # HTTPRequestMethod + '\n' +
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
369 # CanonicalURI + '\n' +
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
370 # CanonicalQueryString + '\n' +
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
371 # CanonicalHeaders + '\n' +
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
372 # SignedHeaders + '\n' +
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
373 # HexEncode(Hash(RequestPayload))
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
374 parts = [method,
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
375 canonical_uri,
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
376 canonical_query,
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
377 canonical_header_string,
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
378 signed_headers,
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
379 hashed_payload]
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
380 canonical_request = '\n'.join(parts)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
381 return canonical_request
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
382
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
383 def signed_request(self, url, method='GET', headers=None):
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
384 """
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
385 prepare a request:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
386 http://docs.python-requests.org/en/latest/user/advanced/#prepared-requests
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
387 """
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
388
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
389 # parse the URL, since we like doing that so much
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
390 parsed = urlparse.urlsplit(url)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
391
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
392 # setup the headers
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
393 if headers is None:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
394 headers = {}
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
395 headers = OrderedDict(headers).copy()
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
396 mapping = dict([(key.lower(), key) for key in headers])
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
397 # XXX this is..."fun"
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
398 # maybe we should just x-form everything to lowercase now?
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
399 # ensure host header is set
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
400 if 'host' not in mapping:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
401 headers['Host'] = parsed.netloc
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
402 # add the `x-amz-date` in terms of now:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
403 # http://docs.aws.amazon.com/AmazonS3/latest/API/RESTCommonRequestHeaders.html
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
404 if 'x-amz-date' not in mapping:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
405 headers['x-amz-date'] = self.datetime()
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
406
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
407 # create a PreparedRequest
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
408 req = requests.Request(method, url, headers)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
409 prepped = req.prepare()
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
410
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
411 # return a signed version
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
412 return self.sign_request(prepped)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
413
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
414 def sign_request(self, request):
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
415 """
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
416 sign a request;
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
417 http://docs.aws.amazon.com/general/latest/gr/sigv4-create-string-to-sign.html
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
418 """
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
419
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
420 # ensure that we have a `x-amz-date` header in the request
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
421 request_date = request.headers.get('x-amz-date')
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
422 # Food for thought: perhaps here is a more appropriate place
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
423 # to add the headers? probably. Likely.
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
424 if request_date is None:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
425 raise NotImplementedError('TODO')
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
426
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
427 # get the canonical request
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
428 canonical_request = self.canonical_request(method=request.method,
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
429 url=request.url,
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
430 headers=request.headers)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
431
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
432 # Create a digest (hash) of the canonical request
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
433 # with the same algorithm that you used to hash the payload.
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
434 hashed_request = self.hash(canonical_request)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
435
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
436 # Create the string to sign:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
437 # http://docs.aws.amazon.com/general/latest/gr/sigv4-create-string-to-sign.html
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
438 # 1. Start with the algorithm designation
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
439 parts = [self.algorithm]
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
440 # 2. Append the request date value
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
441 parts.append(request_date) # XXX we could validate the format
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
442 # 3. Append the credential scope value
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
443 date_string = request_date.split('T')[0] # XXX could do better
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
444 credential_scope = self.credential_scope(date_string)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
445 parts.append(credential_scope)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
446 # 4. Append the hash of the canonical request
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
447 parts.append(hashed_request)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
448 string_to_sign = '\n'.join(parts)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
449
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
450 # Calculate the AWS Signature Version 4
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
451 # http://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
452 # 1. Derive your signing key.
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
453 signing_key = self.signature_key(date_string)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
454 # 2. Calculate the signature
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
455 signature = hmac.new(signing_key,
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
456 string_to_sign.encode('utf-8'),
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
457 hashlib.sha256).hexdigest()
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
458
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
459 # Add the signing information to the request
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
460 # http://docs.aws.amazon.com/general/latest/gr/sigv4-add-signature-to-request.html
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
461 authorization = self.authorization_header.format(algorithm=self.algorithm,
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
462 access_key=self.access_key,
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
463 credential_scope=credential_scope,
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
464 signed_headers=self.signed_headers(request.headers),
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
465 signature=signature)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
466 request.headers['Authorization'] = authorization
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
467
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
468 # return the prepared requests
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
469 return request
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
470
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
471
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
472 def main(args=sys.argv[1:]):
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
473 """CLI"""
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
474
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
475 # parse command line
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
476 parser = argparse.ArgumentParser(description=__doc__)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
477 parser.add_argument('--credentials', '--print-credentials',
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
478 dest='print_credentials',
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
479 action='store_true', default=False,
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
480 help="print default credentials for instance")
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
481 parser.add_argument('--url', dest='url',
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
482 help="hit this URL with a signed HTTP GET request")
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
483 parser.add_argument('--service', dest='service', default='es',
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
484 help="AWS service to use")
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
485 parser.add_argument('--region', dest='region', default='us-west-1',
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
486 help="AWS region")
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
487 # TODO: `service` and `region` come from
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
488 # http://docs.aws.amazon.com/general/latest/gr/sigv4-create-string-to-sign.html
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
489 # We need to be able to derive the region from the environment.
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
490 # It would be very nice to derive the service from, say, the host
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
491 options = parser.parse_args(args)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
492
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
493 if options.url:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
494
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
495 # get credentials
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
496 credentials = AWSCredentials()()
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
497 if not credentials:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
498 parser.error("No AWS credentials found")
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
499 aws_key, aws_secret = credentials
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
500
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
501 # make a signed request to the URL and exit
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
502 request = SignedRequest(aws_key,
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
503 aws_secret,
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
504 region=options.region,
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
505 service=options.service)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
506 response = request(options.url, method='GET')
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
507 print ('-'*10)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
508 print (response.text)
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
509 response.raise_for_status()
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
510 return
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
511
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
512 # metadata interface
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
513 metadata = EC2Metadata()
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
514
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
515 # get desired data
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
516 if options.print_credentials:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
517 data = metadata.credentials()
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
518 else:
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
519 data = metadata()
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
520
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
521 # display data
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
522 print (json.dumps(data, indent=2, sort_keys=True))
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
523
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
524
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
525 if __name__ == '__main__':
0f44ee073173 fake salt, initial commit
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
526 main()