-
Notifications
You must be signed in to change notification settings - Fork 0
/
ec2_vpn.py
98 lines (85 loc) · 3.22 KB
/
ec2_vpn.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
"""Functions to handle listing, running and terminating EC2 instances
for VPN usage.
"""
import boto3
import time
from botocore.exceptions import ClientError
def launch_instance(launch_template_name, region='us-east-1'):
"""Launches an EC2 instance purposed for an on-the-fly VPN,
based on a launch template defined earlier. Note that the template
corresponding to ```launch_template_name``` must already exist.
Returns a two-member tuple of (Instance ID, Instance IP Address),
or None if unsuccessful.
Arguments:
launch_template_name -- The name of the EC2 launch template
region -- The AWS region to deploy the VPN in (default: us-east-1)
"""
s = boto3.client('ec2', region_name=region)
try:
response = s.run_instances(
MinCount=1,
MaxCount=1,
LaunchTemplate={
'LaunchTemplateName': launch_template_name
}
)
instance_id = response['Instances'][0]['InstanceId']
time.sleep(2) # As it turns out, sometimes it takes time for an IP to be assigned
instance = boto3.resource('ec2', region_name=region).Instance(instance_id)
return (instance_id, instance.public_ip_address)
except ClientError:
raise # will be handled by app.py's exception handler
except Exception as e:
print(f'Error creating instance: {e}')
return None
def list_instances(region='us-east-1'):
"""Returns a list of dicts describing running EC2 instances
(tagged as VPNs). The `id` key represents the instance ID (InstanceId)
and the `ip` key represents the instance's public IPv4 address (PublicIpAddress)
Arguments:
region -- The AWS region to check for instances in (default: us-east-1)
"""
s = boto3.client('ec2', region_name=region)
response = s.describe_instances(
Filters=[
{
'Name': 'instance-state-name',
'Values': ['running', 'pending']
},
{
'Name': 'tag:instance_type',
'Values': ['vpn']
}
]
)
reservations = response.get('Reservations')
instances = []
if reservations:
try:
instances = [{'id': x['Instances'][0]['InstanceId'], 'ip': x['Instances'][0]['PublicIpAddress']} for x in reservations]
except Exception as e:
print(f'Error fetching instance list: {e}')
raise
return instances
def terminate_instances(region='us-east-1'):
"""Terminates all active VPN instances (only one should be running at
a time in a given region by default).
Returns the number of instances terminated.
Arguments:
region -- The AWS region to check for instances in (default: us-east-1)
"""
s = boto3.client('ec2', region_name=region)
# Get currently running VPNs:
instances = list_instances(region=region)
instance_ids = [x['id'] for x in instances]
# Terminate any all at once:
if len(instance_ids) > 0:
try:
response = s.terminate_instances(
InstanceIds=instance_ids
)
return len(response['TerminatingInstances'])
except Exception as e:
print(e)
return 0
return 0