大量のIP RangeリストをAWS Security Groupに反映するスクリプト(メモ)

Security Groupのルールを設定する雑スクリプトです。作業メモ的に残しておきます。

Azure PipelineのIPが多すぎ（100個以上）、デフォルトでSecurity GroupのRuleは60個まで。という面倒な状態だったので、雑にPythonスクリプト作りました。

## 背景（前提？）的なもの

- AWS側Security Groupで、IP制限している。
    - Azureのサービス（Azure Pipeline等）からAWS側に接続したいがIP制限でNGになる。
- 設定すべきプロトコルとポートは、HTTPS:443 だけで充分。
- Azureで使用されるIPは下記URLで公開されている（JSONファイルでダウンロードできる）。
    - https://www.microsoft.com/en-us/download/details.aspx?id=56519
    - APIでIPレンジを取得する事もできるが、とりあえず手メンテ。

## スクリプト

Python3で、ソースコードを３ファイルに分けてます。同じフォルダに入れてください。

- main.py
    - このファイル内に書いてあるSecurity Group IDを修正してから実行。
    - 60 ルール毎にSG分割する想定（Part1とPart2）。120個を超える場合は、SG（Part3）を追加してください。
- aws_sg.py
    - awsへの更新処理
- azure_ip_range.py
    - 設定したいIPのリスト。自動で最新情報を取得はしてないので、必要に応じて修正

## main.py

```python
'''
usage: 
$ export AWS_DEFAULT_REGION=ap-northeast-1
$ python main.py
'''
import os
import aws_sg
import azure_ip_range

## TODO: Security Goupr id が決め打ち（ソース内で固定）。

print('AWS_DEFAULT_REGION: %s' % os.getenv("AWS_DEFAULT_REGION"))

def main():

    IP_LIST = azure_ip_range.get_ip_list()

    # Divide rule by 60 ranges. AWS の制限（60 rules/security group)
    SECURITY_GROUP_ID_1 = "sg-XXXXXXXXXXXXXXXXX" # Azure.DevOps.part1
    SECURITY_GROUP_ID_2 = "sg-XXXXXXXXXXXXXXXXX" # Azure.DevOps.part2

    ip_permissions_1 = aws_sg.build_ip_permissions(IP_LIST[:60], 'AzureCloud.eastasia')
    ip_permissions_2 = aws_sg.build_ip_permissions(IP_LIST[60:], 'AzureCloud.eastasia')

    # Clear inbound rules of Security Group 
    aws_sg.revoke_all_ingress(SECURITY_GROUP_ID_1)
    aws_sg.revoke_all_ingress(SECURITY_GROUP_ID_2)

    # set ip limitation
    aws_sg.set_ip_limitations(SECURITY_GROUP_ID_1, ip_permissions_1)
    aws_sg.set_ip_limitations(SECURITY_GROUP_ID_2, ip_permissions_2)

    print('Ingress Successfully Set: %s' % SECURITY_GROUP_ID_1)
    print('Ingress Successfully Set: %s' % SECURITY_GROUP_ID_2)

if __name__ == "__main__":
    main()
```

## aws_sg.py

```python
import boto3
from botocore.exceptions import ClientError


def build_ip_permissions(ip_list, desc):
    '''
    build permission for HTTPS Access
    '''

    ip_ranges = [ {'CidrIp': ip, 'Description': desc} for ip in ip_list]

    return [
        {'IpProtocol': 'tcp', 'FromPort': 443, 'ToPort': 443, 'IpRanges':ip_ranges}
    ]


def revoke_all_ingress(security_group_id):

    # Specify Security group by id
    sg = boto3.resource('ec2').SecurityGroup(security_group_id)

    # remove all Ip Permissions
    if sg.ip_permissions:
        res = sg.revoke_ingress(IpPermissions=sg.ip_permissions)


def set_ip_limitations(security_group_id, ip_permissions):

    # Set Ip permissions for Ingress
    res = boto3.client('ec2').authorize_security_group_ingress(
        GroupId=security_group_id,
        IpPermissions=ip_permissions
    )
    return res
```

## azure_ip_range.py

```python
def get_ip_list():
    return IP_LIST

# 
# TODO: Get ip range from Web API(like this.)
# -------------powershell
# $body = @{“region”=“asiaeast”;“request”=“dcip”} | ConvertTo-Json
# $webrequest = Invoke-WebRequest -Method “POST” -uri https://azuredcip.azurewebsites.net/api/azuredcipranges -Body $body
# ConvertFrom-Json -InputObject $webrequest.Content
# -------------
#  See: https://social.technet.microsoft.com/wiki/contents/articles/50886.azure-get-datacenter-ip-address-ranges-via-api.aspx
# 
#
# 以下、下記URLからダウンロードしたJSONファイルの中から、
# "name": "AzureCloud.eastasia"の部分を切り出したもの。
# 
# See: https://www.microsoft.com/en-us/download/confirmation.aspx?id=56519
IP_LIST = [
    "13.70.0.0/18",
    "13.72.192.0/19",
    ...
]

```