
はじめに
AWSのSecurityGroupの数がだいぶ多くなってきて、中には既に使われていないものもあり、SecurityGroupの整理を行うことになりました。その際削除して良いSecurityGroupを絞り込むために行った対応を備忘のために残したいと思います。
SecurityGroupのリスト取得
まず下記のコマンドで全てのSecurityGroupのGroupIdを取得します。(出力はJSONの配列で出力されます。)
aws ec2 describe-security-groups --query 'SecurityGroups[].GroupId'
SecurityGroupに紐づいているENI(ElasticNetworkInterface)の取得
取得してきたSecurityGroupに対して、紐づいているElasticNetworkInterfaceと用途を確認するための情報を取得してきます。下記のコマンドで対象SecurityGroupに紐づいているENIの取得が可能です。
aws ec2 describe-network-interfaces \
--filters Name=group-id,Values="sg-xxxxxxx" \
--query 'NetworkInterfaces[].{
ENI: NetworkInterfaceId,
Type: InterfaceType,
Status: Status,
Attachment: Attachment.InstanceId,
Description: Description,
PrivateIp: PrivateIpAddress
}'
| Name | 意味 |
|---|---|
| NetworkInterfaceId | 紐づけられているENIのID |
| InterfaceType | ENIの用途 |
| Status | 現在の状態 |
| Attachment.InstanceId | アタッチされているEC2のインスタンスID |
| Description | 説明文 |
| PrivateIpAddress | 紐づけられているプライベートアドレス |
(一件一件手作業で取るのは面倒なのでここはスクリプトで取得しました。)
使われているものの中で、想定外の使われ方をしているものがないかの確認を行う用途があったので、その他の情報についても取得していますが、使われてないものを確認するだけであれば NetworkInterfaceId との紐付けだけ確認できればOKです。
ここで確認したSecurityGroupのうち、NetworkInterfaceIdと紐づいていないSecurityGroupが、現在使われていない可能性が高いSecurityGroupとなります。
紐づけがないSecurityGroupの確認
先程 "可能性が高い" と言ったのは、それらについても現時点でENIと紐づいていないだけで、実際には使われている可能性があるからです。
というのも、EMRやECSといったサービスでは、実行時にだけインスタンスが起動して、実行中だけENIと紐づいている状態になり、実行完了後にはインスタンスが破棄されてしまうのでENIとの紐づけが解除されてしまうためです。
そのため、それらのサービスで一時的にでもENIと紐づけが行われたか、というのをCloudTrailで確認します。
CloudTrailには過去90日分の管理イベントが残されているので、そこからCreateNetworkInterfaceのイベントと、RunInstancesのイベントを取得して確認していきます。
ECSで起動される際にはCreateNetworkInterfaceイベントに残るのですが、EMRで起動される時にはインスタンスグループで設定しているEC2インスタンスが起動されRunInstancesにイベントが残る形になっているため、2種類のイベントを確認する必要があります。
下記のコマンドで2026年1月分のイベントについて、時刻とイベント内容をそれぞれ取得しました。
CreateNetworkInterfaceイベントの取得
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=EventName,AttributeValue=CreateNetworkInterface \
--query 'Events[].{
EventTime: EventTime,
CloudTrailEvent: CloudTrailEvent
}' \
--start-time 2026-01-01T00:00:00Z \
--end-time 2026-01-31T23:59:59Z > create_network_instance.json
RunInstancesイベントの取得
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=EventName,AttributeValue=RunInstances \
--query 'Events[].{
EventTime: EventTime,
CloudTrailEvent: CloudTrailEvent
}' \
--start-time 2026-01-01T00:00:00Z \
--end-time 2026-01-31T23:59:59Z > run_instances.json
イベントからSecurityGroup利用の確認
取得したイベントの情報に対して、ENIと紐付けされていないSecurityGroupの利用があったかどうかを確認します。
下記のコマンドのような形でチェックが可能です。(下記の確認ではjqコマンドを利用していますので、別途jqのインストールが必要になります)
CreateNetworkInstanceのログから対象SecurityGroupに対してENIの紐づけが行われた時刻のリストを取得する
jq -r '.[]
| select(.CloudTrailEvent | contains("sg-xxxxx"))
| .EventTime' create_network_instance.json
RunInstancesのログから対象SecurityGroupに紐づいたEC2インスタンスが起動した時刻のリストを取得する
jq -r '.[]
| select(.CloudTrailEvent | contains("sg-xxxxx"))
| .EventTime' run_instances.json
(こちらも一件一件の確認は手間なので、スクリプトで利用がなかったSecurityGroupだけを抽出していきました。)
使われていないSecurityGroup
上記のイベントのチェックでも利用履歴のなかったSecurityGroupについてはほぼ使用していないものと見てよいかと思います。
とはいえ、CloudTrailの保持期間を超えて利用していないだけで、極稀に利用する可能性がある、というようなものもあり得るため、上記までの確認で使われていない可能性の高いとされたSecurityGroupに対しても最終的には目視でチェックしたうえで、対応を進めることになります。
まとめ
既に構築されてしまっているリソースに対してはどうしても、こういった対応が必要になってくるのですが、大量のSecurityGroupに対して一件一件確認するよりは、AWS CLIから逆引きで確認していくことで効率的に対象を絞り込めたかと思います。