-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgenerateCredentialsReport.py
257 lines (230 loc) · 9.9 KB
/
generateCredentialsReport.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
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
import argparse as argparse
import boto3 as boto3
import datetime as datetime
import emoji as emoji
import logging as logging
import os as os
import platform as platform
import requests as requests
import subprocess as subprocess # nosec - B404:import_subprocess
import sys as sys
import time as time
from botocore.exceptions import ClientError
from shutil import get_terminal_size as get_terminal_size
from shutil import which as which
logger = logging.getLogger(__name__)
def main():
"""
Take in the arguments and generate a credentials report.
you must have the following AWS IAM permissions:
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": [
"iam:GenerateCredentialReport",
"iam:GetCredentialReport"
],
"Resource": "*"
}
}
"""
# Configure logging.
logging.basicConfig(level=logging.ERROR,
format='%(levelname)s: %(message)s')
# Add arguments to the parser.
parser = argparse.ArgumentParser(exit_on_error=False)
# The AWS region argument
parser.add_argument('-r', '--region',
help='The AWS region you wish to execute the script in.',
default='us-east-1',
choices=(
'af-south-1',
'ap-east-1',
'ap-northeast-1',
'ap-northeast-2',
'ap-south-1',
'ap-south-2',
'ap-southeast-1',
'ap-southeast-2',
'ap-southeast-3',
'ap-southeast-4',
'ca-central-1',
'cn-north-1',
'cn-northwest-1',
'eu-central-1',
'eu-central-2',
'eu-north-1',
'eu-south-1',
'eu-west-1',
'eu-west-2',
'eu-west-3',
'me-south-1',
'me-central-1',
'sa-east-1',
'us-east-1',
'us-east-2',
'us-gov-east-1',
'us-gov-west-1',
'us-west-1',
'us-west-2'
)
)
# The AWS CLI profile argument
parser.add_argument('-p', '--profile',
help='AWS profile',
default='default')
# The file name argument
parser.add_argument('-f', '--filename',
help='The name of the file to download the report to.',
default='credentialsReport.csv')
# The open in excel argument
parser.add_argument('-o', '--open',
help='Open the file in Excel.',
action='store_true')
# Parse the arguments.
args = parser.parse_args()
"""
The below outputs are for making the end user support staff lives easier;
especially when dealing with end user PEBKAC & PICNIC issues.
"""
# Display the computer platform that this script is running on.
print(emoji.emojize(":computer: Platform: {}",
language='alias').format(platform.platform()))
# Display the version of Python that this script is running with
print(emoji.emojize(":snake: Python version: {}",
language='alias').format(sys.version))
# Check that the Python version is 3 or higher.
if sys.version_info[0] < 3:
print(emoji.emojize(
'You must use Python 3 or higher :cross_mark:',
language='alias'))
raise ValueError("You must use Python 3 or higher")
else:
print(emoji.emojize(
'Python version is OK :check_mark_button:',
language='alias'))
# Check that the AWS CLI is installed.
if which('aws') is None:
print(emoji.emojize(
'AWS CLI is not installed :cross_mark:',
language='alias'))
raise ValueError("AWS CLI is not installed")
else:
print(emoji.emojize(
'AWS CLI is installed :check_mark_button:',
language='alias'))
# Get the version of the AWS CLI.
aws_cli_version = subprocess.check_output(
['aws', '--version']).decode('utf-8').split(' ')[0] # nosec B603 B607
# Check that the AWS CLI version is less than verson 2.
if int(aws_cli_version.split('/')[1].split('.')[0]) < 2:
# Print an error message and raise an exception.
print(emoji.emojize(
'You must use AWS CLI version 2 or higher :heavy_exclamation_mark:',
language='alias'))
raise ValueError("You must use AWS CLI version 2 or higher")
else:
# Display the version of the AWS CLI.
print(emoji.emojize(":ok: AWS CLI version: {}", language='alias').format(
aws_cli_version.split('/')[1]))
# Display the version of the Boto3 library.
print(emoji.emojize(":package: Boto3 version: {}",
language='alias').format(boto3.__version__))
# Display the version of the Requests library.
print(emoji.emojize(":package: Requests version: {}",
language='alias').format(requests.__version__))
# Display the version of the Emoji library.
print(emoji.emojize(":package: Emoji version: {}",
language='alias').format(emoji.__version__))
# Display the version of the Argparse library.
print(emoji.emojize(":package: Argparse version: {}",
language='alias').format(argparse.__version__))
# Display the version of the Logging library.
print(emoji.emojize(":package: Logging version: {}",
language='alias').format(logging.__version__))
# Display the version of the Platform library.
print(emoji.emojize(":package: Platform version: {}",
language='alias').format(platform.__version__))
# Display the values of the command-line arguments.
print(f"AWS Region: {args.region}")
print(f"AWS CLI Profile: {args.profile}")
print(f"File name: {args.filename}")
# Create a Boto3 session using the specified profile and region.
session = boto3.Session(profile_name=args.profile,
region_name=args.region)
# Create a Boto3 client for Amazon IAM.
s3_client = session.client('iam',
use_ssl=True,
verify=True
)
# Generate the credential report.
try:
s3_client.generate_credential_report()
except ClientError as e:
print(e)
raise ValueError("Could not generate the credential report") from e
else:
print("Credential report being generated")
# Wait for the credential report to be generated.
print("Waiting for the credential report to be generated")
while True:
try:
credential_report = s3_client.get_credential_report()
except ClientError as e:
print(e)
raise ValueError("Could not get the credential report") from e
else:
# Check if the credential report is ready.
if credential_report['Content']:
print("Credential report ready")
break
else:
print("Credential report not ready yet. Waiting another 5 seconds")
time.sleep(5)
# Write the credential report to a file.
print(emoji.emojize(
":open_file_folder: Writing the credential report to {}").format(args.filename))
with open(args.filename, 'w') as f:
f.write(credential_report['Content'].decode('utf-8'))
if args.open:
# determine if platform is Windows, Linux or Mac
if platform.system() == 'Windows':
# check if Excel is installed
if which('excel.exe') is None:
print(emoji.emojize(
'Excel is not installed :cross_mark:',
language='alias'))
raise ValueError("Excel is not installed")
else:
print(emoji.emojize(
":open_file_folder: Opening {} in Excel in Windows").format(args.filename))
# nosec B605: start is used to open a file with excel.exe
os.system(f'start excel.exe {args.filename}')
elif platform.system() == 'Linux':
# check if LibreOffice is installed
if which('libreoffice') is None:
print(emoji.emojize(
'LibreOffice is not installed :cross_mark:',
language='alias'))
raise ValueError("LibreOffice is not installed")
else:
print(emoji.emojize(
":open_file_folder: Opening {} in LibreOffice in Linux").format(args.filename))
# nosec B605: libreoffice is used to open a file with LibreOffice
os.system(f'libreoffice {args.filename}')
elif platform.system() == 'Darwin':
# check if Excel is installed
if which('Microsoft Excel') is None:
print(emoji.emojize(
'Excel is not installed :cross_mark:',
language='alias'))
raise ValueError("Excel is not installed")
else:
print(emoji.emojize(
":open_file_folder: Opening {} in Excel in Mac").format(args.filename))
# nosec B605: open is used to open a file with Microsoft Excel
os.system(f'open -a "Microsoft Excel" {args.filename}')
print(emoji.emojize(":white_check_mark: Done :white_check_mark:"))
if __name__ == "__main__":
main()