-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathscenario_create_user_assume_role.py
241 lines (209 loc) · 8.72 KB
/
scenario_create_user_assume_role.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
"""
Purpose
Shows how to use AWS SDK for Python (Boto3) to create an IAM user, assume a role,
and perform AWS actions.
1. Create a user who has no permissions.
2. Create a role that grants permission to list Amazon S3 buckets for the account.
3. Add a policy to let the user assume the role.
4. Assume the role and list Amazon S3 buckets using temporary credentials.
5. Delete the policy, role, and user.
"""
# snippet-start:[python.example_code.iam.Scenario_CreateUserAssumeRole]
import json
import sys
import time
from uuid import uuid4
import boto3
from botocore.exceptions import ClientError
def progress_bar(seconds):
"""Shows a simple progress bar in the command window."""
for _ in range(seconds):
time.sleep(1)
print('.', end='')
sys.stdout.flush()
print()
def setup(iam_resource):
"""
Creates a new user with no permissions.
Creates an access key pair for the user.
Creates a role with a policy that lets the user assume the role.
Creates a policy that allows listing Amazon S3 buckets.
Attaches the policy to the role.
Creates an inline policy for the user that lets the user assume the role.
:param iam_resource: A Boto3 AWS Identity and Access Management (IAM) resource
that has permissions to create users, roles, and policies
in the account.
:return: The newly created user, user key, and role.
"""
try:
user = iam_resource.create_user(UserName=f'demo-user-{uuid4()}')
print(f"Created user {user.name}.")
except ClientError as error:
print(f"Couldn't create a user for the demo. Here's why: "
f"{error.response['Error']['Message']}")
raise
try:
user_key = user.create_access_key_pair()
print(f"Created access key pair for user.")
except ClientError as error:
print(f"Couldn't create access keys for user {user.name}. Here's why: "
f"{error.response['Error']['Message']}")
raise
print(f"Wait for user to be ready.", end='')
progress_bar(10)
try:
role = iam_resource.create_role(
RoleName=f'demo-role-{uuid4()}',
AssumeRolePolicyDocument=json.dumps({
'Version': '2012-10-17',
'Statement': [{
'Effect': 'Allow',
'Principal': {'AWS': user.arn},
'Action': 'sts:AssumeRole'}]}))
print(f"Created role {role.name}.")
except ClientError as error:
print(f"Couldn't create a role for the demo. Here's why: "
f"{error.response['Error']['Message']}")
raise
try:
policy = iam_resource.create_policy(
PolicyName=f'demo-policy-{uuid4()}',
PolicyDocument=json.dumps({
'Version': '2012-10-17',
'Statement': [{
'Effect': 'Allow',
'Action': 's3:ListAllMyBuckets',
'Resource': 'arn:aws:s3:::*'}]}))
role.attach_policy(PolicyArn=policy.arn)
print(f"Created policy {policy.policy_name} and attached it to the role.")
except ClientError as error:
print(f"Couldn't create a policy and attach it to role {role.name}. Here's why: "
f"{error.response['Error']['Message']}")
raise
try:
user.create_policy(
PolicyName=f'demo-user-policy-{uuid4()}',
PolicyDocument=json.dumps({
'Version': '2012-10-17',
'Statement': [{
'Effect': 'Allow',
'Action': 'sts:AssumeRole',
'Resource': role.arn}]}))
print(f"Created an inline policy for {user.name} that lets the user assume "
f"the role.")
except ClientError as error:
print(f"Couldn't create an inline policy for user {user.name}. Here's why: "
f"{error.response['Error']['Message']}")
raise
print("Give AWS time to propagate these new resources and connections.", end='')
progress_bar(10)
return user, user_key, role
def show_access_denied_without_role(user_key):
"""
Shows that listing buckets without first assuming the role is not allowed.
:param user_key: The key of the user created during setup. This user does not
have permission to list buckets in the account.
"""
print(f"Try to list buckets without first assuming the role.")
s3_denied_resource = boto3.resource(
's3', aws_access_key_id=user_key.id, aws_secret_access_key=user_key.secret)
try:
for bucket in s3_denied_resource.buckets.all():
print(bucket.name)
raise RuntimeError("Expected to get AccessDenied error when listing buckets!")
except ClientError as error:
if error.response['Error']['Code'] == 'AccessDenied':
print("Attempt to list buckets with no permissions: AccessDenied.")
else:
raise
# snippet-start:[iam.python.assume_role.complete]
def list_buckets_from_assumed_role(user_key, assume_role_arn, session_name):
"""
Assumes a role that grants permission to list the Amazon S3 buckets in the account.
Uses the temporary credentials from the role to list the buckets that are owned
by the assumed role's account.
:param user_key: The access key of a user that has permission to assume the role.
:param assume_role_arn: The Amazon Resource Name (ARN) of the role that
grants access to list the other account's buckets.
:param session_name: The name of the STS session.
"""
sts_client = boto3.client(
'sts', aws_access_key_id=user_key.id, aws_secret_access_key=user_key.secret)
try:
response = sts_client.assume_role(
RoleArn=assume_role_arn, RoleSessionName=session_name)
temp_credentials = response['Credentials']
print(f"Assumed role {assume_role_arn} and got temporary credentials.")
except ClientError as error:
print(f"Couldn't assume role {assume_role_arn}. Here's why: "
f"{error.response['Error']['Message']}")
raise
# Create an S3 resource that can access the account with the temporary credentials.
s3_resource = boto3.resource(
's3',
aws_access_key_id=temp_credentials['AccessKeyId'],
aws_secret_access_key=temp_credentials['SecretAccessKey'],
aws_session_token=temp_credentials['SessionToken'])
print(f"Listing buckets for the assumed role's account:")
try:
for bucket in s3_resource.buckets.all():
print(bucket.name)
except ClientError as error:
print(f"Couldn't list buckets for the account. Here's why: "
f"{error.response['Error']['Message']}")
raise
# snippet-end:[iam.python.assume_role.complete]
def teardown(user, role):
"""
Removes all resources created during setup.
:param user: The demo user.
:param role: The demo role.
"""
try:
for attached in role.attached_policies.all():
policy_name = attached.policy_name
role.detach_policy(PolicyArn=attached.arn)
attached.delete()
print(f"Detached and deleted {policy_name}.")
role.delete()
print(f"Deleted {role.name}.")
except ClientError as error:
print("Couldn't detach policy, delete policy, or delete role. Here's why: "
f"{error.response['Error']['Message']}")
raise
try:
for user_pol in user.policies.all():
user_pol.delete()
print("Deleted inline user policy.")
for key in user.access_keys.all():
key.delete()
print("Deleted user's access key.")
user.delete()
print(f"Deleted {user.name}.")
except ClientError as error:
print("Couldn't delete user policy or delete user. Here's why: "
f"{error.response['Error']['Message']}")
def usage_demo():
"""Drives the demonstration."""
print('-'*88)
print(f"Welcome to the IAM create user and assume role demo.")
print('-'*88)
iam_resource = boto3.resource('iam')
user = None
role = None
try:
user, user_key, role = setup(iam_resource)
print(f"Created {user.name} and {role.name}.")
show_access_denied_without_role(user_key)
list_buckets_from_assumed_role(user_key, role.arn, 'AssumeRoleDemoSession')
except Exception:
print("Something went wrong!")
finally:
if user is not None and role is not None:
teardown(user, role)
print("Thanks for watching!")
if __name__ == '__main__':
usage_demo()
# snippet-end:[python.example_code.iam.Scenario_CreateUserAssumeRole]