Имеется VPN сервис, работающий в AWS на EC2, доступ к которому ограничен с помощью security group.
Задача: набросать скрипт, который работал бы под Linux/Windows (VPN-ом пользуюсь не я один), который позволял бы быстро добавить запись с новым IP для доступа.
Используем Python 3 и boto3
.
Содержание
Зависимости
Первым делом – необходимо придумать как установить зависимости, в частности – библиотеку boto3
, что бы упростить жизнь пользователю (хотя Python всё-равно придётся устанавливать вручную).
Добавляем функцию pip_install()
:
... def pip_install(pkg_name): pip.main(['install', pkg_name]) ...
И её вызов, сейчас скрипт полностью выглядит так:
#!/usr/bin/env python import sys import pip def pip_install(pkg_name): pip.main(['install', pkg_name]) if __name__ == '__main__': print('\nChecking for dependencies...') try: import boto3 print('boto3 library already installed - OK.\n') except ImportError: print('boto3 not found - going to install it now...\n') pip_install('boto3') print('\nDone - please, restart script nnow.\n') exit(0)
Запускаем, проверяем:
[simterm]
$ ./aws_update_setevoy_vpn_sg.py Checking for dependencies... boto3 library already installed - OK.
[/simterm]
AWS IAM пользователь
Теперь, прежде чем продолжать – добавим отдельного пользователя, у которого будет доступ только к определённой security group.
Создаём новую IAM policy с правами DescribeSecurityGroups и AuthorizeSecurityGroupIngress:
Создаём пользователя с programmatic access (доступ в AWS Console ему совсем не нужен):
Подключаем ему созданную политику:
Проверяем доступ.
Задаём переменные для авторизации:
[simterm]
$ export AWS_ACCESS_KEY_ID=AKI***WNA
$ export AWS_SECRET_ACCESS_KEY=oaZ***uMW
[/simterm]
Пробуем получить список EC2 машин, к которому доступа мы не давали (DescribeInstances):
[simterm]
$ aws ec2 describe-instances An error occurred (UnauthorizedOperation) when calling the DescribeInstances operation: You are not authorized to perform this operation.
[/simterm]
Хорошо, и пробуем получить список групп безопасности – тут права заданы, доступ должен быть:
[simterm]
$ aws ec2 describe-security-groups --output text SECURITYGROUPS rtfm_prod_db_access sg-3e723c58 rtfm_prod_db_access 264418146286 vpc-3941cb5c IPPERMISSIONS 3306 tcp 3306 ...
[/simterm]
ОК, работает.
boto3
EC2 client
Теперь можно приступать к работе с ресурсами AWS.
Первым делом – создаём клиент – EC2.Client
:
... def create_conn(aws_access_key, aws_secret_key, ec2_region): conn = boto3.client('ec2', aws_access_key_id=aws_access_key, aws_secret_access_key=aws_secret_key, region_name=ec2_region) return conn ...
Добавляем вызов этой функции:
... # create boto3 connection first client = create_conn('AKI***EZQ', '+HKp***k1P', 'eu-west-1')
Добавление rule
Добавляем ещё одну функцию add_rule()
, в которой вызываем метод authorize_security_group_ingress()
из объекта client
:
... def add_rule(client, sg_id, cidr): client.authorize_security_group_ingress(GroupId=sg_id, IpProtocol='udp',CidrIp=cidr,FromPort=1194,ToPort=1194)
И добавляем запуск всего, теперь скрипт полностью выглядит так:
#!/usr/bin/env python import sys import pip def pip_install(pkg_name): pip.main(['install', pkg_name]) def create_conn(aws_access_key, aws_secret_key, ec2_region): conn = boto3.client('ec2', aws_access_key_id=aws_access_key, aws_secret_access_key=aws_secret_key, region_name=ec2_region) return conn def add_rule(client, sg_id, cidr): client.authorize_security_group_ingress(GroupId=sg_id, IpProtocol='udp',CidrIp=cidr,FromPort=1194,ToPort=1194) if __name__ == '__main__': # check for first argument assert(len(sys.argv) == 2) print('\nChecking for dependencies...') try: import boto3 print('boto3 library already installed - OK.\n') except ImportError: print('boto3 not found - going to install it now...\n') pip_install('boto3') print('\nDone - please, restart script nnow.\n') exit(0) # add /32 mask to an IP cidr = sys.argv[1] + '/32' # vars aws_access_key = 'AKI***WNA' aws_secret_key = 'oaZ***uMW' ec2_region = 'eu-west-1' sg_id = 'sg-7cdef305' # create boto3 connection first print('Creating connection...') client = create_conn(aws_access_key, aws_secret_key, ec2_region) # add new rule with IP from first arg print('Adding new rule with IP {}...'.format(cidr)) add_rule(client, sg_id, cidr) print('\nDone.\n')
Запускаем:
[simterm]
$ ./aws_update_setevoy_vpn_sg.py 0.0.0.0 Checking for dependencies... boto3 library already installed - OK. Creating connection... Adding new rule with IP 0.0.0.0/32... Done.
[/simterm]
Проверяем:
[simterm]
$ aws ec2 describe-security-groups --group-ids sg-7cdef305 --output text ... IPPERMISSIONS 1194 udp 1194 ... IPRANGES 0.0.0.0/32
[/simterm]
Готово:
ToDoBetter
Что хорошо было бы добавить в этот скрипт – это:
- авторизация – было бы правильнее реализовать через
~/.aws/credentials
или через переменные окружения (см. тут>>>), а не хардкодить прямо в скрипт, но т.к. на машине пользователя AWS CLI нет, а рассказывать как в Windows добавить переменные – не хочется, то передаём так; - удаление старого правила – но тут надо сделать выборку по полю Description каждого правила, а в
boto3
я такой возможности не нашёл; - добавить описание для добавляемого правила, но опять-таки – см. п. 1.