5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

SpeeeAdvent Calendar 2019

Day 1

AWS Configを駆使して使っていないSecurity Groupをお掃除する

Last updated at Posted at 2019-12-01

この記事はSpeee Advent Calendar 2019 1日目の記事です。

あらすじ

長い間AWSアカウントを運用していると、様々な理由で不要なリソースというものが生まれます。

  • 長く運用されているアカウントで昔のリソースがIaCされていなくて使われなくなったリソースが残り続けていたり
  • dev兼用だったりして不意に誰かの検証リソースが残っていたり
  • などなど理由は様々です

使ってないリソースは消すに限ります。
本記事では、使ってないSecurityGroupをAWS Configを使って洗い出す方法をご紹介します。

AWS Config

AWS Configには様々な機能がありますが、機能の一つにAWSリソース間の依存関係をSQLライクなクエリで抽出する機能があります。
https://docs.aws.amazon.com/ja_jp/config/latest/developerguide/querying-AWS-resources.html

使ったことがない方向けに雰囲気を共有するためにAWS Configのサンプルクエリを一つ紹介します。
下記は使っていないEBSボリュームを抽出するクエリです。

SELECT
    resourceId,
    resourceType,
    configuration.volumeType,
    configuration.size,
    resourceCreationTime,
    tags,
    configuration.encrypted,
    configuration.availabilityZone,
    configuration.state.value
WHERE
    resourceType = 'AWS::EC2::Volume'
    AND configuration.state.value <> 'in-use'

AWS ConfigのクエリはAWS Config用のデータのみを参照するのでFROM句は使いません。
基本的にSELECTとWHEREで欲しい情報の列と行を絞る感じになります。
JOINはサポートしていないけどGROUP BYはあります。HAVING BYはないです。

実際に使っていないSecurityGroupを抽出する方法

では実際に使っていないSecurityGroupを抽出していきます。

紹介するクエリはコンソールかCLIかSDKかなんらか方法で実行して下さい。
得られた結果を加工したりするので得意な言語のSDKがおすすめです。

Step1:他のAWSリソースから参照されているSecurityGroupを出す

まずは以下のクエリを実行します。

SELECT
    relationships.resourceId
WHERE
    resourceType != 'AWS::EC2::VPC' AND
    relationships.resourceType = 'AWS::EC2::SecurityGroup'
GROUP BY
    relationships.resourceId

このクエリを実行するとセキュリティグループを参照しているリソース(例えばELB)が参照しているリソース(例えばELBが参照しているVPC,SecurityGroup,Subnet)のID一覧を得ることができます。
ややこしいですね。

クエリを少し解説すると、WHERE句のrelationships.resourceType = 'AWS::EC2::SecurityGroup'はSecurityGroupを参照しているAWSリソースを抽出しています。relationshipsというカラムにそのリソースが参照している依存関係の情報があります。
VPCを除いているのは、全てのSecurityGroupはVPCに紐付けられるのでVPCにしか参照されていない(つまり他から使われていない)SecurityGroupもクエリに含められてしまうからです。

GROUP BYは参照先のリソースIDで集約しています。

このクエリを実行するとSecurityGroup以外にもVPCやSubnetのIDも含まれてしまうので、得られた結果のうちを sg- から始まるidだけをスクリプトか何かで抽出します。
本当はHavingが使えればそこで絞れて良いのですが...

最終的にここで抽出されたSecurityGroupのIdは、何かのawsリソースから参照されているSecurityGroupの一覧になります。

Step2:他のAWSリソースから参照されていないSecurityGroupを出す

全SecurityGroup - 他のAWSリソースから参照されているSecurityGroup = 他のAWSリソースから参照されていないSecurityGroupです。

以下のクエリを実行します。

SELECT
    resourceId,
    resourceName
WHERE
    resourceType = 'AWS::EC2::SecurityGroup' AND
    resourceId NOT IN (
        'sg-xxxxxx',
        'sg-yyyyyy',
        'sg-zzzzzz',
        ...
    )

IN句に入れるIDはstep1で抽出したIDになります。サブクエリとか使えると良いんですがね..

これで晴れて他のAWSリソースから参照されていないSecurityGroupの一覧が出せました。

Step3:SecurityGroupのルールで参照されているSecurityGroupを除く

もう一つ考慮するケースがあって他のSecurityGroupのsrcやdestに指定されているSecurityGroupは消すことができません。

なのでSecurityGroupのルールとして使われているSecurityGroupを除きます。

Step2:で得られたSecurityGroupIdに対して何らスクリプトでループを回して各SecurityGroupIdに対して以下のクエリを実行します。
(この辺もうちょいいい感じでクエリ書けるかもしれません)

SELECT
    *
WHERE
    resourceType = 'AWS::EC2::SecurityGroup' AND (
    	configuration.ipPermissions.userIdGroupPairs.groupId = 'sg-xxxxxx'
      OR
      configuration.ipPermissionsEgress.userIdGroupPairs.groupId = 'sg-xxxxxx'
 )

SELECTの結果が0ならどのSecurityGroupにも参照されていません。消せる候補です。

終わりに

以上のステップで使っていないSecurityGroupを洗い出すことができました。あとは一覧をチェックして消すのみです。一応消す前は人の目を挟んだ方がいいと思います。

不要なゴミは消して快適なAWS運用を実現しましょう!!

5
3
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?