Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aws
GitHub Repository: aws/aws-cli
Path: blob/develop/awscli/customizations/datapipeline/createdefaultroles.py
1567 views
1
# Copyright 2015 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
# Class to create default roles for datapipeline
15
16
import logging
17
import warnings
18
from awscli.customizations.datapipeline.constants \
19
import DATAPIPELINE_DEFAULT_SERVICE_ROLE_NAME, \
20
DATAPIPELINE_DEFAULT_RESOURCE_ROLE_NAME, \
21
DATAPIPELINE_DEFAULT_SERVICE_ROLE_ARN, \
22
DATAPIPELINE_DEFAULT_RESOURCE_ROLE_ARN, \
23
DATAPIPELINE_DEFAULT_SERVICE_ROLE_ASSUME_POLICY, \
24
DATAPIPELINE_DEFAULT_RESOURCE_ROLE_ASSUME_POLICY
25
from awscli.customizations.commands import BasicCommand
26
from awscli.customizations.datapipeline.translator \
27
import display_response, dict_to_string, get_region
28
from awscli.utils import create_nested_client
29
30
from botocore.exceptions import ClientError
31
32
LOG = logging.getLogger(__name__)
33
34
35
_DEPRECATION_NOTICE = """
36
Support for this command has been deprecated and may fail to create these roles
37
if they do not already exist. For more information on managing these policies
38
manually see the following documentation:
39
40
https://docs.aws.amazon.com/datapipeline/latest/DeveloperGuide/dp-iam-roles.html
41
"""
42
43
_DESCRIPTION = """
44
NOTE: {}
45
46
Creates the default IAM role "{}" and "{}" which are used while creating an EMR
47
cluster.
48
49
If these roles do not exist, create-default-roles will automatically create
50
them and set their policies.
51
52
If these roles have already been created create-default-roles will not update
53
their policies.
54
"""
55
56
57
class CreateDefaultRoles(BasicCommand):
58
59
NAME = "create-default-roles"
60
_UNDOCUMENTED = True
61
DESCRIPTION = _DESCRIPTION.format(
62
_DEPRECATION_NOTICE,
63
DATAPIPELINE_DEFAULT_SERVICE_ROLE_NAME,
64
DATAPIPELINE_DEFAULT_RESOURCE_ROLE_NAME,
65
)
66
67
def __init__(self, session, formatter=None):
68
super(CreateDefaultRoles, self).__init__(session)
69
70
def _run_main(self, parsed_args, parsed_globals, **kwargs):
71
"""Call to run the commands"""
72
self._region = get_region(self._session, parsed_globals)
73
self._endpoint_url = parsed_globals.endpoint_url
74
self._iam_client = create_nested_client(
75
self._session, 'iam',
76
region_name=self._region,
77
endpoint_url=self._endpoint_url,
78
verify=parsed_globals.verify_ssl
79
)
80
warnings.warn(_DEPRECATION_NOTICE)
81
return self._create_default_roles(parsed_args, parsed_globals)
82
83
def _create_role(self, role_name, role_arn, role_policy):
84
"""Method to create a role for a given role name and arn
85
if it does not exist
86
"""
87
88
role_result = None
89
role_policy_result = None
90
# Check if the role with the name exists
91
if self._check_if_role_exists(role_name):
92
LOG.debug('Role ' + role_name + ' exists.')
93
else:
94
LOG.debug('Role ' + role_name + ' does not exist.'
95
' Creating default role for EC2: ' + role_name)
96
# Create a create using the IAM Client with a particular triplet
97
# (role_name, role_arn, assume_role_policy)
98
role_result = self._create_role_with_role_policy(role_name,
99
role_policy,
100
role_arn)
101
role_policy_result = self._get_role_policy(role_arn)
102
return role_result, role_policy_result
103
104
def _construct_result(self, dpl_default_result,
105
dpl_default_policy,
106
dpl_default_res_result,
107
dpl_default_res_policy):
108
"""Method to create a resultant list of responses for create roles
109
for service and resource role
110
"""
111
112
result = []
113
self._construct_role_and_role_policy_structure(result,
114
dpl_default_result,
115
dpl_default_policy)
116
self._construct_role_and_role_policy_structure(result,
117
dpl_default_res_result,
118
dpl_default_res_policy)
119
return result
120
121
def _create_default_roles(self, parsed_args, parsed_globals):
122
123
# Setting the role name and arn value
124
(datapipline_default_result,
125
datapipline_default_policy) = self._create_role(
126
DATAPIPELINE_DEFAULT_SERVICE_ROLE_NAME,
127
DATAPIPELINE_DEFAULT_SERVICE_ROLE_ARN,
128
DATAPIPELINE_DEFAULT_SERVICE_ROLE_ASSUME_POLICY)
129
130
(datapipline_default_resource_result,
131
datapipline_default_resource_policy) = self._create_role(
132
DATAPIPELINE_DEFAULT_RESOURCE_ROLE_NAME,
133
DATAPIPELINE_DEFAULT_RESOURCE_ROLE_ARN,
134
DATAPIPELINE_DEFAULT_RESOURCE_ROLE_ASSUME_POLICY)
135
136
# Check if the default EC2 Instance Profile for DataPipeline exists.
137
instance_profile_name = DATAPIPELINE_DEFAULT_RESOURCE_ROLE_NAME
138
if self._check_if_instance_profile_exists(instance_profile_name):
139
LOG.debug('Instance Profile ' + instance_profile_name + ' exists.')
140
else:
141
LOG.debug('Instance Profile ' + instance_profile_name +
142
'does not exist. Creating default Instance Profile ' +
143
instance_profile_name)
144
self._create_instance_profile_with_role(instance_profile_name,
145
instance_profile_name)
146
147
result = self._construct_result(datapipline_default_result,
148
datapipline_default_policy,
149
datapipline_default_resource_result,
150
datapipline_default_resource_policy)
151
152
display_response(self._session, 'create_role', result, parsed_globals)
153
154
return 0
155
156
def _get_role_policy(self, arn):
157
"""Method to get the Policy for a particular ARN
158
This is used to display the policy contents to the user
159
"""
160
pol_det = self._iam_client.get_policy(PolicyArn=arn)
161
policy_version_details = self._iam_client.get_policy_version(
162
PolicyArn=arn, VersionId=pol_det["Policy"]["DefaultVersionId"])
163
return policy_version_details["PolicyVersion"]["Document"]
164
165
def _create_role_with_role_policy(
166
self, role_name, assume_role_policy, role_arn):
167
"""Method to create role with a given rolename, assume_role_policy
168
and role_arn
169
"""
170
# Create a role using IAM client CreateRole API
171
create_role_response = self._iam_client.create_role(
172
RoleName=role_name, AssumeRolePolicyDocument=dict_to_string(
173
assume_role_policy))
174
175
# Create a role using IAM client AttachRolePolicy API
176
self._iam_client.attach_role_policy(PolicyArn=role_arn,
177
RoleName=role_name)
178
179
return create_role_response
180
181
def _construct_role_and_role_policy_structure(
182
self, list_val, response, policy):
183
"""Method to construct the message to be displayed to the user"""
184
# If the response is not none they we get the role name
185
# from the response and
186
# append the policy information to the response
187
if response is not None and response['Role'] is not None:
188
list_val.append({'Role': response['Role'], 'RolePolicy': policy})
189
return list_val
190
191
def _check_if_instance_profile_exists(self, instance_profile_name):
192
"""Method to verify if a particular role exists"""
193
try:
194
# Client call to get the instance profile with that name
195
self._iam_client.get_instance_profile(
196
InstanceProfileName=instance_profile_name)
197
198
except ClientError as e:
199
# If the instance profile does not exist then the error message
200
# would contain the required message
201
if e.response['Error']['Code'] == 'NoSuchEntity':
202
# No instance profile error.
203
return False
204
else:
205
# Some other error. raise.
206
raise e
207
208
return True
209
210
def _check_if_role_exists(self, role_name):
211
"""Method to verify if a particular role exists"""
212
try:
213
# Client call to get the role
214
self._iam_client.get_role(RoleName=role_name)
215
except ClientError as e:
216
# If the role does not exist then the error message
217
# would contain the required message.
218
if e.response['Error']['Code'] == 'NoSuchEntity':
219
# No role error.
220
return False
221
else:
222
# Some other error. raise.
223
raise e
224
225
return True
226
227
def _create_instance_profile_with_role(self, instance_profile_name,
228
role_name):
229
"""Method to create the instance profile with the role"""
230
# Setting the value for instance profile name
231
# Client call to create an instance profile
232
self._iam_client.create_instance_profile(
233
InstanceProfileName=instance_profile_name)
234
235
# Adding the role to the Instance Profile
236
self._iam_client.add_role_to_instance_profile(
237
InstanceProfileName=instance_profile_name, RoleName=role_name)
238
239