AWS CDKによる【セキュリティグループ】の構築

皆様こんにちは。
AWS CDKを利用してマルチAZ3層アーキテクチャ構築をしていきます。
この記事ではセキュリティグループの作成を行います。

目次はこちら

1.セキュリティグループとは

セキュリティグループ(Security Group)は、AWSのネットワークセキュリティ機能で、EC2インスタンスやRDSデータベースなどのリソースに対するトラフィックのアクセス制御を行います。

概要

  • ファイアウォールの役割:セキュリティグループは、AWSの仮想ファイアウォールとして機能し、リソースへの入出力トラフィックを制御します。

  • インバウンドルール: リソースに対する着信トラフィックを制御します。例えば、特定のIPアドレスからのHTTPトラフィックを許可するなど。

  • アウトバウンドルール: リソースからの発信トラフィックを制御します。例えば、特定のIPアドレスへの接続を許可するなど。

  • 状態の保持:セキュリティグループは「ステートフル」で、インバウンドルールで許可されたトラフィックは、対応するアウトバウンドルールも自動的に許可されます。逆も同様です。

  • デフォルト設定:新規作成時には、デフォルトで全てのインバウンドトラフィックが拒否され、全てのアウトバウンドトラフィックが許可されます。

  • タグ付け:タグを使用して、セキュリティグループを管理しやすくすることができます。例えば、環境ごとに異なるタグを付けるなど。

  • 複数のリソースへの適用:一つのセキュリティグループは複数のEC2インスタンスなどのリソースに適用でき、リソース間でセキュリティ設定を一貫して管理できます。

詳細は公式ドキュメントを参照ください。

2.目的

各リソースごとに通信が必要な最小限の許可ポリシーを設定したセキュリティグループの作成。

①EC2用:ALB、VPCエンドポイント(SSM用)、RDS、EFSのインバウンド通信を許可
②RDS用:EC2のインバウンド通信を許可
③ALB用:HTTP、HTTPSのすべてのインバウンド通信を許可
④EFS用:EC2のインバウンド通信を許可
⑤VPCエンドポイント(SSM)用:EC2のインバウンド通信を許可

※セキュリティグループはステートフルであるためアウトバウンドについては設定不要

3.構成図

4.全体構築ソースコード

        # セキュリティグループの作成
        ec2_sg = ec2.SecurityGroup(self, "kitaya-sg-ec2",
            vpc=vpc,
            description="sg for ec2",
            allow_all_outbound=True
        )
        Tags.of(ec2_sg).add("Name", "kitaya-sg-ec2")

        rds_sg = ec2.SecurityGroup(self, "kitaya-sg-db",
            vpc=vpc,
            description="sg for db",
            allow_all_outbound=True
        )
        Tags.of(rds_sg).add("Name", "kitaya-sg-db")

        alb_sg = ec2.SecurityGroup(self, "kitaya-sg-alb",
            vpc=vpc,
            description="sg for alb",
            allow_all_outbound=True
        )
        Tags.of(alb_sg).add("Name", "kitaya-sg-alb")

        efs_sg = ec2.SecurityGroup(self, "kitaya-sg-efs",
            vpc=vpc,
            description="sg for efs",
            allow_all_outbound=True
        )
        Tags.of(efs_sg).add("Name", "kitaya-sg-efs")

        ssm_vpce_sg = ec2.SecurityGroup(self, "kitaya-ssm-sg-vpce",
            vpc=vpc,
            description="sg for ssm vpc endpoint",
            allow_all_outbound=True
        )
        Tags.of(ssm_vpce_sg).add("Name", "kitaya-ssm-sg-vpce")

        # 各セキュリティグループにインバウンドルールを追加
        # EC2
        ec2_sg.connections.allow_from(alb_sg, ec2.Port.tcp(443), "Allow HTTPS access")
        ec2_sg.connections.allow_from(ssm_vpce_sg, ec2.Port.tcp(80), "Allow HTTP access")
        ec2_sg.connections.allow_from(rds_sg, ec2.Port.tcp(3306), "Allow MySQL access")
        ec2_sg.connections.allow_from(efs_sg, ec2.Port.tcp(2049), "Allow NFS access")

        # RDS
        rds_sg.connections.allow_from(ec2_sg, ec2.Port.tcp(3306), "Allow MySQL access")

        # ALB
        alb_sg.connections.allow_from(ec2.Peer.any_ipv4(), ec2.Port.tcp(443), "Allow HTTPS access")
        alb_sg.connections.allow_from(ec2.Peer.any_ipv4(), ec2.Port.tcp(80), "Allow HTTP access")

        # EFS
        efs_sg.connections.allow_from(ec2_sg, ec2.Port.tcp(2049), "Allow NFS access")

5.ソースコード詳細

5-1.セキュリティグループの作成

まずは必要なセキュリティグループをすべて作成します。

  • "ec2.SecurityGroup"クラスを使用
    リソースを作成する際に必要なコンストラクトの指定と論理ID(テンプレート内で一意)の指定をしたのち、詳細のプロパティを指定しています。
    ※他リソースでも同様

プロパティは下記

使用するプロパティ 設定値 説明
vpc vpc セキュリティグループが属するVPCを指定
description ソースコード参照 セキュリティグループの説明
allow_all_outbound True すべてのアウトバウンドトラフィックを許可するかどうかを指定
今回はすべて許可のため"True"
  • "Tags.of()"メソッドを使用してNameタグをつけます(書式は下記)
    Tags.of("リソース名").add("キー", "値")

  • ソースコード

 # VPCの作成
        # セキュリティグループの作成
        ec2_sg = ec2.SecurityGroup(self, "kitaya-sg-ec2",
            vpc=vpc,
            description="sg for ec2",
            allow_all_outbound=True
        )
        Tags.of(ec2_sg).add("Name", "kitaya-sg-ec2")

        rds_sg = ec2.SecurityGroup(self, "kitaya-sg-db",
            vpc=vpc,
            description="sg for db",
            allow_all_outbound=True
        )
        Tags.of(rds_sg).add("Name", "kitaya-sg-db")

        alb_sg = ec2.SecurityGroup(self, "kitaya-sg-alb",
            vpc=vpc,
            description="sg for alb",
            allow_all_outbound=True
        )
        Tags.of(alb_sg).add("Name", "kitaya-sg-alb")

        efs_sg = ec2.SecurityGroup(self, "kitaya-sg-efs",
            vpc=vpc,
            description="sg for efs",
            allow_all_outbound=True
        )
        Tags.of(efs_sg).add("Name", "kitaya-sg-efs")

        ssm_vpce_sg = ec2.SecurityGroup(self, "kitaya-ssm-sg-vpce",
            vpc=vpc,
            description="sg for ssm vpc endpoint",
            allow_all_outbound=True
        )
        Tags.of(ssm_vpce_sg).add("Name", "kitaya-ssm-sg-vpce")

5-2.各セキュリティグループにインバウンドルールを追加

  • "connections.allow_from"を使用
    下記の書式で記載しています。
    "ルールを追加するセキュリティグループ".connections.allow_from(許可するソース, ec2.Port."プロトコル"("ポート"), "説明文")

ALBからEC2インスタンスへのHTTPS (ポート443) アクセスを許可するセキュリティグループルールを追加

ec2_sg.connections.allow_from(alb_sg, ec2.Port.tcp(443), "Allow HTTPS access")

ec2_sg: EC2インスタンス用のセキュリティグループ
connections: セキュリティグループの接続ルールを管理するプロパティ
allow_from: ソースセキュリティグループからのインバウンドトラフィックを許可するメソッド
alb_sg: ALB用のセキュリティグループ
ec2.Port.tcp(443): TCPプロトコルのポート443 (HTTPS) を指定
"Allow HTTPS access": ルールの説明

  • ソースコード
        # 各セキュリティグループにインバウンドルールを追加
        # EC2
        ec2_sg.connections.allow_from(alb_sg, ec2.Port.tcp(443), "Allow HTTPS access")
        ec2_sg.connections.allow_from(ssm_vpce_sg, ec2.Port.tcp(80), "Allow HTTP access")
        ec2_sg.connections.allow_from(rds_sg, ec2.Port.tcp(3306), "Allow MySQL access")
        ec2_sg.connections.allow_from(efs_sg, ec2.Port.tcp(2049), "Allow NFS access")

        # RDS
        rds_sg.connections.allow_from(ec2_sg, ec2.Port.tcp(3306), "Allow MySQL access")

        # ALB
        alb_sg.connections.allow_from(ec2.Peer.any_ipv4(), ec2.Port.tcp(443), "Allow HTTPS access")
        alb_sg.connections.allow_from(ec2.Peer.any_ipv4(), ec2.Port.tcp(80), "Allow HTTP access")

        # EFS
        efs_sg.connections.allow_from(ec2_sg, ec2.Port.tcp(2049), "Allow NFS access")

6.感想

インバウンドルールの追加で循環依存関係が発生していまいましたが、connections.allow_fromを使用することで解決できました。
マネジメントコンソールでの構築と違い、選択肢が多いので今後も調べながら進めていこうと思います。

Last modified: 2024-08-07

Author