AWS Configでリソースに紐付かないセキュリティグループを抽出
tl;dr
- 使っていないセキュリティグループを列挙したい
- セキュリティグループはENIに対して割り当て、ENIがEC2などのリソースにアタッチされている。使っていないセキュリティグループ = どのENIにも割り当てられていないセキュリティグループ、なのだが、取得するのはセキュリティグループを列挙し、ENIを列挙して、という作業が必要でEC2 API叩いて処理するの地味に面倒
- AWS Configを有効にしているなら、クエリでいい感じにとれるし、リージョンもまたげるし、Aggregatorを使っているならマルチアカウントも一発
コード
import json import boto3 client = boto3.client('config') query = "SELECT resourceId, awsRegion, resourceName, " \ "configuration.description, configuration.ipPermissions, " \ "configuration.ipPermissionsEgress, relationships " \ "WHERE resourceType = 'AWS::EC2::SecurityGroup'" results = [] response = client.select_resource_config(Expression=query, Limit=100) results.extend(response['Results']) while True: if 'NextToken' in response: response = client.select_resource_config(Expression=query, NextToken=response['NextToken'], Limit=100) results.extend(response['Results']) else: break for result in results: result = json.loads(result) for relationship in result['relationships']: if relationship['resourceType'] == 'AWS::EC2::NetworkInterface': #eni_id = relationship['resourceId'] break else: # 関連するENIが無い = リソースに関連付けられていないセキュリティグループ print('\t'.join( [result['awsRegion'], result['resourceId'], result['resourceName'], result['configuration']['description']]))
マルチアカウント版コード
select_aggregate_resource_config()
に差し替えるだけで、AWS Config Aggregatorに対してクエリを実行できます。便利。
import json import boto3 client = boto3.client('config') query = "SELECT accountId, resourceId, awsRegion, resourceName, " \ "configuration.description, configuration.ipPermissions, " \ "configuration.ipPermissionsEgress, relationships " \ "WHERE resourceType = 'AWS::EC2::SecurityGroup'" results = [] response = client.select_aggregate_resource_config(Expression=query, Limit=100, ConfigurationAggregatorName='<aggregator name>') results.extend(response['Results']) while True: if 'NextToken' in response: response = client.select_aggregate_resource_config(Expression=query, NextToken=response['NextToken'], Limit=100, ConfigurationAggregatorName='<aggregator name>') results.extend(response['Results']) else: break for result in results: result = json.loads(result) for relationship in result['relationships']: if relationship['resourceType'] == 'AWS::EC2::NetworkInterface': #eni_id = relationship['resourceId'] break else: # 関連するENIが無い = リソースに関連付けられていないセキュリティグループ print('\t'.join( ['"' + result['accountId'] + '"', result['awsRegion'], result['resourceId'], result['resourceName'], result['configuration']['description']]))