forked from elpy1/ssh-over-ssm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ssm-tool.py
118 lines (96 loc) · 4.32 KB
/
ssm-tool.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
#!/usr/bin/env python3
import argparse
import boto3
import datetime
import os
import sys
from dateutil.tz import tzlocal
from boto3.session import Session
def get_profiles():
try:
aws_profiles = Session().available_profiles
return aws_profiles
except Exception as e:
print(f"ERROR: {e}")
sys.exit(1)
def process_args():
parser = argparse.ArgumentParser(description='ssh-ssm toolkit')
group = parser.add_mutually_exclusive_group()
parser.add_argument('--profile', dest='profile', action='store', choices=get_profiles(), default=os.getenv('AWS_PROFILE') or 'default', metavar='', help='AWS profile. default is \'default\'')
group.add_argument('-u', '--update', action='store_true', help='update ssm-agent on returned instances')
group.add_argument('-i', '--iid', dest='iidonly', action='store_true', help='return only instance ids')
parser.add_argument('-x', '--linux', dest='platforms', action='append_const', const='Linux', help='filter only linux machines')
parser.add_argument('-w', '--windows', dest='platforms', action='append_const', const='Windows', help='filter only windows machines')
parser.add_argument('-t', '--tag', dest='tag', action='store', default='Name:*', metavar='key:value', help='filter by ec2 tag. default value is \'Name:*\'')
return parser.parse_args()
def get_ec2_name(iid):
ec2r = session.resource('ec2')
try:
etags = ec2r.Instance(iid).tags
name = [tag['Value'] for tag in etags if tag['Key'] == 'Name']
return name[0] if name else ''
except Exception as e:
print(f"ERROR: {e}")
def filtered_instances(filter):
try:
resp = ec2.describe_instances(Filters=[filter])
return resp['Reservations']
except Exception as e:
print(f"ERROR: {e}")
def ssm_update_agent(iidlist):
try:
resp = ssm.send_command(
InstanceIds=iidlist,
DocumentName='AWS-UpdateSSMAgent',
DocumentVersion='$LATEST')
if resp['ResponseMetadata']['HTTPStatusCode'] == 200:
print('success')
except Exception as e:
print(f"ERROR: {e}")
def ssm_list_instances(filter):
try:
ssminstances = ssm.describe_instance_information(MaxResults=50, Filters=[filter])
ssmi = ssminstances['InstanceInformationList']
while True:
next_token = ssminstances.get('NextToken')
if not next_token: break
ssminstances = ssm.describe_instance_information(MaxResults=50, Filters=[filters], NextToken=next_token)
ssmi.extend(ssminstances['InstanceInformationList'])
return ssmi
except Exception as e:
print(f"ERROR:{e}")
def build_table(ssmi, filtered):
names = [get_ec2_name(i.get('InstanceId')) for i in ssmi if i['InstanceId'] in filtered]
instances = [i.get('InstanceId') for i in ssmi if i['InstanceId'] in filtered]
ips = [i.get('IPAddress') for i in ssmi if i['InstanceId'] in filtered]
updates = [i.get('IsLatestVersion') for i in ssmi if i['InstanceId'] in filtered]
versions = [i.get('PlatformName') for i in ssmi if i['InstanceId'] in filtered]
titles = ['instance id', 'ip', 'agent up-to-date', 'platform', 'names']
data = [titles] + list(zip(instances, ips, updates, versions, names))
return data
args = process_args()
session = Session(profile_name=args.profile)
ec2 = session.client('ec2')
ssm = session.client('ssm')
# ssm platform filter
platform = {'Key': 'PlatformTypes', 'Values': (args.platforms or ['Linux', 'Windows'])}
# ec2 tag filter
tags = args.tag.split(':')
if args.iidonly and tags[1].startswith('ssm.'): tags[1] = tags[1].strip('ssm.')
tag = {'Name': f"tag:{tags[0]}", 'Values': [tags[1]]}
# list ssm instances
ssmi = ssm_list_instances(platform)
# query ec2 describe instances and apply filter
filtered = [i.get('InstanceId') for x in filtered_instances(tag) for i in x.get('Instances')]
# match filtered ec2 instances with ssm instances
matched = [i.get('InstanceId') for i in ssmi if i.get('InstanceId') in filtered]
if not args.update and not args.iidonly:
data = build_table(ssmi, filtered)
for i, d in enumerate(data):
line = '|'.join(str(x).ljust(22) for x in d)
print(line)
if i == 0: print('-' * len(line))
elif args.update:
ssm_update_agent(matched)
elif args.iidonly:
print(*matched, sep='\n')