Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aws
GitHub Repository: aws/aws-cli
Path: blob/develop/awscli/customizations/ec2/decryptpassword.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
import logging
14
import os
15
import base64
16
import rsa
17
18
from botocore import model
19
20
from awscli.arguments import BaseCLIArgument
21
22
23
logger = logging.getLogger(__name__)
24
25
26
HELP = """<p>The file that contains the private key used to launch
27
the instance (e.g. windows-keypair.pem). If this is supplied, the
28
password data sent from EC2 will be decrypted before display.</p>"""
29
30
31
def ec2_add_priv_launch_key(argument_table, operation_model, session,
32
**kwargs):
33
"""
34
This handler gets called after the argument table for the
35
operation has been created. It's job is to add the
36
``priv-launch-key`` parameter.
37
"""
38
argument_table['priv-launch-key'] = LaunchKeyArgument(
39
session, operation_model, 'priv-launch-key')
40
41
42
class LaunchKeyArgument(BaseCLIArgument):
43
44
def __init__(self, session, operation_model, name):
45
self._session = session
46
self.argument_model = model.Shape('LaunchKeyArgument', {'type': 'string'})
47
self._operation_model = operation_model
48
self._name = name
49
self._key_path = None
50
self._required = False
51
52
@property
53
def cli_type_name(self):
54
return 'string'
55
56
@property
57
def required(self):
58
return self._required
59
60
@required.setter
61
def required(self, value):
62
self._required = value
63
64
@property
65
def documentation(self):
66
return HELP
67
68
def add_to_parser(self, parser):
69
parser.add_argument(self.cli_name, dest=self.py_name,
70
help='SSH Private Key file')
71
72
def add_to_params(self, parameters, value):
73
"""
74
This gets called with the value of our ``--priv-launch-key``
75
if it is specified. It needs to determine if the path
76
provided is valid and, if it is, it stores it in the instance
77
variable ``_key_path`` for use by the decrypt routine.
78
"""
79
if value:
80
path = os.path.expandvars(value)
81
path = os.path.expanduser(path)
82
if os.path.isfile(path):
83
self._key_path = path
84
endpoint_prefix = \
85
self._operation_model.service_model.endpoint_prefix
86
event = 'after-call.%s.%s' % (endpoint_prefix,
87
self._operation_model.name)
88
self._session.register(event, self._decrypt_password_data)
89
else:
90
msg = ('priv-launch-key should be a path to the '
91
'local SSH private key file used to launch '
92
'the instance.')
93
raise ValueError(msg)
94
95
def _decrypt_password_data(self, parsed, **kwargs):
96
"""
97
This handler gets called after the GetPasswordData command has been
98
executed. It is called with the and the ``parsed`` data. It checks to
99
see if a private launch key was specified on the command. If it was,
100
it tries to use that private key to decrypt the password data and
101
replace it in the returned data dictionary.
102
"""
103
if self._key_path is not None:
104
logger.debug("Decrypting password data using: %s", self._key_path)
105
value = parsed.get('PasswordData')
106
if not value:
107
return
108
try:
109
with open(self._key_path) as pk_file:
110
pk_contents = pk_file.read()
111
private_key = rsa.PrivateKey.load_pkcs1(pk_contents.encode("latin-1"))
112
value = base64.b64decode(value)
113
value = rsa.decrypt(value, private_key)
114
logger.debug(parsed)
115
parsed['PasswordData'] = value.decode('utf-8')
116
logger.debug(parsed)
117
except Exception:
118
logger.debug('Unable to decrypt PasswordData', exc_info=True)
119
msg = ('Unable to decrypt password data using '
120
'provided private key file.')
121
raise ValueError(msg)
122
123