株式会社CINC 開発本部(旧:開発部) エンジニアブログ

開発部→開発本部!!ビッグデータ取得/分析・自然言語処理・人工知能(AI)を用いた開発を軸に、マーケティングソリューションの開発や、DX推進を行っている、株式会社CINCの開発本部です。

AWS CLIで未使用SecurityGroupを効率的に特定する方法

AWS CLIで未使用SecurityGroupを効率的に特定する方法

はじめに

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から逆引きで確認していくことで効率的に対象を絞り込めたかと思います。