Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aws
GitHub Repository: aws/aws-cli
Path: blob/develop/awscli/customizations/ec2/bundleinstance.py
1567 views
1
# Copyright 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
#
3
# Licensed under the Apache License, Version 2.0 (the "License"). You
4
# may not use this file except in compliance with the License. A copy of
5
# the License is located at
6
#
7
# http://aws.amazon.com/apache2.0/
8
#
9
# or in the "license" file accompanying this file. This file is
10
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11
# ANY KIND, either express or implied. See the License for the specific
12
# language governing permissions and limitations under the License.
13
14
import logging
15
from hashlib import sha1
16
import hmac
17
import base64
18
import datetime
19
20
from awscli.arguments import CustomArgument
21
from awscli.compat import get_current_datetime
22
23
logger = logging.getLogger('ec2bundleinstance')
24
25
# This customization adds the following scalar parameters to the
26
# bundle-instance operation:
27
28
# --bucket:
29
BUCKET_DOCS = ('The bucket in which to store the AMI. '
30
'You can specify a bucket that you already own or '
31
'a new bucket that Amazon EC2 creates on your behalf. '
32
'If you specify a bucket that belongs to someone else, '
33
'Amazon EC2 returns an error.')
34
35
# --prefix:
36
PREFIX_DOCS = ('The prefix for the image component names being stored '
37
'in Amazon S3.')
38
39
# --owner-akid
40
OWNER_AKID_DOCS = 'The access key ID of the owner of the Amazon S3 bucket.'
41
42
# --policy
43
POLICY_DOCS = (
44
"An Amazon S3 upload policy that gives "
45
"Amazon EC2 permission to upload items into Amazon S3 "
46
"on the user's behalf. If you provide this parameter, "
47
"you must also provide "
48
"your secret access key, so we can create a policy "
49
"signature for you (the secret access key is not passed "
50
"to Amazon EC2). If you do not provide this parameter, "
51
"we generate an upload policy for you automatically. "
52
"For more information about upload policies see the "
53
"sections about policy construction and signatures in the "
54
'<a href="http://docs.aws.amazon.com/AmazonS3/latest/dev'
55
'/HTTPPOSTForms.html">'
56
'Amazon Simple Storage Service Developer Guide</a>.')
57
58
# --owner-sak
59
OWNER_SAK_DOCS = ('The AWS secret access key for the owner of the '
60
'Amazon S3 bucket specified in the --bucket '
61
'parameter. This parameter is required so that a '
62
'signature can be computed for the policy.')
63
64
65
def _add_params(argument_table, **kwargs):
66
# Add the scalar parameters and also change the complex storage
67
# param to not be required so the user doesn't get an error from
68
# argparse if they only supply scalar params.
69
storage_arg = argument_table['storage']
70
storage_arg.required = False
71
arg = BundleArgument(storage_param='Bucket',
72
name='bucket',
73
help_text=BUCKET_DOCS)
74
argument_table['bucket'] = arg
75
arg = BundleArgument(storage_param='Prefix',
76
name='prefix',
77
help_text=PREFIX_DOCS)
78
argument_table['prefix'] = arg
79
arg = BundleArgument(storage_param='AWSAccessKeyId',
80
name='owner-akid',
81
help_text=OWNER_AKID_DOCS)
82
argument_table['owner-akid'] = arg
83
arg = BundleArgument(storage_param='_SAK',
84
name='owner-sak',
85
help_text=OWNER_SAK_DOCS)
86
argument_table['owner-sak'] = arg
87
arg = BundleArgument(storage_param='UploadPolicy',
88
name='policy',
89
help_text=POLICY_DOCS)
90
argument_table['policy'] = arg
91
92
93
def _check_args(parsed_args, **kwargs):
94
# This function checks the parsed args. If the user specified
95
# the --ip-permissions option with any of the scalar options we
96
# raise an error.
97
logger.debug(parsed_args)
98
arg_dict = vars(parsed_args)
99
if arg_dict['storage']:
100
for key in ('bucket', 'prefix', 'owner_akid',
101
'owner_sak', 'policy'):
102
if arg_dict[key]:
103
msg = ('Mixing the --storage option '
104
'with the simple, scalar options is '
105
'not recommended.')
106
raise ValueError(msg)
107
108
POLICY = ('{{"expiration": "{expires}",'
109
'"conditions": ['
110
'{{"bucket": "{bucket}"}},'
111
'{{"acl": "ec2-bundle-read"}},'
112
'["starts-with", "$key", "{prefix}"]'
113
']}}'
114
)
115
116
117
def _generate_policy(params):
118
# Called if there is no policy supplied by the user.
119
# Creates a policy that provides access for 24 hours.
120
delta = datetime.timedelta(hours=24)
121
expires = get_current_datetime() + delta
122
expires_iso = expires.strftime("%Y-%m-%dT%H:%M:%S.%fZ")
123
policy = POLICY.format(expires=expires_iso,
124
bucket=params['Bucket'],
125
prefix=params['Prefix'])
126
params['UploadPolicy'] = policy
127
128
129
def _generate_signature(params):
130
# If we have a policy and a sak, create the signature.
131
policy = params.get('UploadPolicy')
132
sak = params.get('_SAK')
133
if policy and sak:
134
policy = base64.b64encode(policy.encode('latin-1')).decode('utf-8')
135
new_hmac = hmac.new(sak.encode('utf-8'), digestmod=sha1)
136
new_hmac.update(policy.encode('latin-1'))
137
ps = base64.encodebytes(new_hmac.digest()).strip().decode('utf-8')
138
params['UploadPolicySignature'] = ps
139
del params['_SAK']
140
141
142
def _check_params(params, **kwargs):
143
# Called just before call but prior to building the params.
144
# Adds information not supplied by the user.
145
storage = params['Storage']['S3']
146
if 'UploadPolicy' not in storage:
147
_generate_policy(storage)
148
if 'UploadPolicySignature' not in storage:
149
_generate_signature(storage)
150
151
152
EVENTS = [
153
('building-argument-table.ec2.bundle-instance', _add_params),
154
('operation-args-parsed.ec2.bundle-instance', _check_args),
155
('before-parameter-build.ec2.BundleInstance', _check_params),
156
]
157
158
159
def register_bundleinstance(event_handler):
160
# Register all of the events for customizing BundleInstance
161
for event, handler in EVENTS:
162
event_handler.register(event, handler)
163
164
165
class BundleArgument(CustomArgument):
166
167
def __init__(self, storage_param, *args, **kwargs):
168
super(BundleArgument, self).__init__(*args, **kwargs)
169
self._storage_param = storage_param
170
171
def _build_storage(self, params, value):
172
# Build up the Storage data structure
173
if 'Storage' not in params:
174
params['Storage'] = {'S3': {}}
175
params['Storage']['S3'][self._storage_param] = value
176
177
def add_to_params(self, parameters, value):
178
if value:
179
self._build_storage(parameters, value)
180
181