皆様こんにちは。
今回はCLIを利用して高可用性アーキテクトの構築をしていきます。
このブログはCLIによるセキュリティグループを構築する上での知識を記事としてまとめ再確認し、皆様と共有するため作成します。
この記事ではセキュリティグループの作成を行います。

1.高可用性アーキテクト構築目次

目次はこちら

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

セキュリティグループは仮想ファイアウォールとして機能し、関連付けられたリソースに到達および離れるトラフィックを制御します。例えば、セキュリティグループを EC2 インスタンスに関連付けると、インスタンスのインバウンドトラフィックとアウトバウンドトラフィックが制御されます。
引用:セキュリティグループを使用してリソースへのトラフィックを制御する

セキュリティグループを利用してリソースのトラフィックを制御することができます。

インバウンドルール

外から中に向けてのトラフィックを制限するルールを設定します。
デフォルトではすべて拒否しています。

アウトバウンドルール

中から外に向けてのトラフィックを制限するルールを設定します。
デフォルトではすべて許可しています。

類似のサービスとしてはサブネット単位で設定する「ネットワークACL」があげられます。

今回はALB,EC2,EFS,RDSの4つのAWSリソースのインバウンドトラフィックをセキュリティグループを利用して制御したいためセキュリティグループを作成します。

3.フロー図

file

  1. ALB用のものはRoute53のパブリックホストゾーンからのトラフィックを受け入れる必要がありますのでソースは0.0.0.0/0とします。通信は暗号化されている必要があるのでタイプはHTTPSにします。
  2. EC2用のものはALBからのトラフィックを受け入れる必要がありますのでソースは上記ALB用のSGを指定します。VPC内部の通信は暗号化されている必要がないのでタイプはHTTPにします。また、自分のPCよりEC2インスタンスと通信するために、SSHでソースはMYIPを指定します。
  3. RDS用のものはEC2に対するDBサーバーとして扱うので、RDS用のものはEC2からのトラフィックを受け入れる必要がありますのでソースはEC2用のSGを指定します。タイプはDBにMYSQLを使用するのでMYSQL/Auroraを選びます。
  4. EFS用のものはEC2のWordpressインストールファイルを共有するために使用しますので、EFS用のものはEC2からのトラフィックを受け入れる必要があります。ソースはEC2用のSGを指定し、タイプNFSを選びます。

4.セキュリティグループ作成

次にこのVPCで使うセキュリティグループ(以下SG)を作成していきます。
今回作成するのはALB用、EC2用、RDS用、EFS用の計四つです。

まずALB用のSGを作成していきます
SGを作成するには、[aws ec2 create-security-group]コマンドを使用します。

使用するオプション 設定値 説明
--group-name umemoto_SG_ALB 設定したいグループネームを入力
--description "dedicated to umemoto ALB" 説明を入力
--vpc-id vpc-xxxxx VPCのIDを入力
--tag-specifications  "ResourceType=security-group,
Tags=[{Key=Name,Value=umemoto_SG_ALB}]"
SGに対しネームタグを追加

入力

aws ec2 create-security-group `
    --group-name umemoto_SG_ALB `
    --description "dedicated to umemoto ALB" `
    --vpc-id vpc-xxxxx `
    --tag-specifications "ResourceType=security-group, Tags=[{Key=Name,Value=umemoto_SG_ALB}]"

出力

{
    "GroupId": "sg-xxxxx",
    "Tags": [
        {
            "Key": "Name",
            "Value": "umemoto_SG_ALB"
        }

次に、ALB用のSGのインバウンドルールにhttps経由でのインターネットからのアクセスを許可します。

ルールを追加するために、[aws ec2 authorize-security-group-ingress]コマンドを使用します。

使用するオプション 設定値 説明
--group-id sg-xxxxx SGのIDを入力
--protocol tcp プロトコルを入力
--port 443,80 アクセスを許可したいプロトコルのポート範囲を入力(HTTPはWordPressでHTTPSを有効にするまで一時的に許可)
--cidr  0.0.0.0/0 設定したいCIDRを入力

入力

aws ec2 authorize-security-group-ingress `
    --group-id sg-xxxxx `
    --protocol tcp --port 443 `
    --cidr 0.0.0.0/0
aws ec2 authorize-security-group-ingress `
    --group-id sg-xxxxx `
    --protocol tcp --port 80 `
    --cidr 0.0.0.0/0

出力

-----//HTTPS許可の出力
{
    "Return": true,
    "SecurityGroupRules": [
        {
            "SecurityGroupRuleId": "sgr-xxxxx",
            "GroupId": "sg-xxxxx",
            "GroupOwnerId": "xxxxx",
            "IsEgress": false,
            "IpProtocol": "tcp",
            "FromPort": 443,
            "ToPort": 443,
            "CidrIpv4": "0.0.0.0/0"
        }
    ]
}
-----//HTTP許可の出力
{
    "Return": true,
    "SecurityGroupRules": [
        {
            "SecurityGroupRuleId": "sgr-xxxxx",
            "GroupId": "sg-xxxxx",
            "GroupOwnerId": "xxxxx",
            "IsEgress": false,
            "IpProtocol": "tcp",
            "FromPort": 80,
            "ToPort": 80,
            "CidrIpv4": "0.0.0.0/0"
        }
    ]
}

ALB用のSGに設定したルールが出力されました。

次にEC2用のSGの作成をしていきます。

使用するオプション 設定値 説明
--group-name umemoto_SG_EC2 設定したいグループネームを入力
--description "dedicated to umemoto EC2" 説明を入力
--vpc-id vpc-xxxxx VPCのIDを入力
--tag-specifications  "ResourceType=security-group,
Tags=[{Key=Name,Value=umemoto_SG_EC2}]"
SGに対しネームタグを追加

入力

aws ec2 create-security-group `
    --group-name umemoto_SG_EC2 `
    --description "dedicated to umemoto EC2" `
    --vpc-id vpc-xxxxx `
    --tag-specifications "ResourceType=security-group, Tags=[{Key=Name,Value=umemoto_SG_EC2}]"

作成の出力はほとんど同じなため省略します。

EC2用のSGは自身がアクセスするためのSSH、そしてALBからのhttpアクセスを許可する二つのルールを追加します。

使用するオプション 設定値 説明
--group-id sg-xxxxx SGのIDを入力
--protocol tcp 説明を入力
--port 80,22 アクセスを許可したいプロトコルのポート範囲を入力
--cidr MYIP/32 自分のグローバルIPを入力
--source-group sg-xxxxx ALB用のSGのIDを入力

入力

aws ec2 authorize-security-group-ingress `
    --group-id sg-xxxxx `
    --protocol tcp --port 80 `
    --source-group  sg-xxxxx
aws ec2 authorize-security-group-ingress `
    --group-id sg-xxxxx `
    --protocol tcp --port 22 `
    --cidr [MYIP]/32

出力

-----//HTTP許可の出力
{
    "Return": true,
    "SecurityGroupRules": [
        {
            "SecurityGroupRuleId": "sgr-xxxxx",
            "GroupId": "sg-xxxxx",
            "GroupOwnerId": "xxxxx",
            "IsEgress": false,
            "IpProtocol": "tcp",
            "FromPort": 80,
            "ToPort": 80,
            "ReferencedGroupInfo": {
                "GroupId": "sg-xxxxx"
            }
        }
    ]
}
-----
-----//SSH許可の出力
{
    "Return": true,
    "SecurityGroupRules": [
        {
            "SecurityGroupRuleId": "sgr-xxxxx",
            "GroupId": "sg-xxxxx",
            "GroupOwnerId": "xxxxx",
            "IsEgress": false,
            "IpProtocol": "tcp",
            "FromPort": 22,
            "ToPort": 22,
            "CidrIpv4": "MYIP/32"
        }
    ]
}

次に、EFSのSGを作成していきます。

使用するオプション 設定値 説明
--group-name umemoto_SG_EFS 設定したいグループネームを入力
--description "dedicated to umemoto EFS" 説明を入力
--vpc-id vpc-xxxxx VPCのIDを入力
--tag-specifications  "ResourceType=security-group,
Tags=[{Key=Name,Value=umemoto_SG_EFS}]"
SGに対しネームタグを追加

入力

aws ec2 create-security-group `
    --group-name umemoto_SG_EFS `
    --description "dedicated to umemoto EFS" `
    --vpc-id vpc-xxxxx `
    --tag-specifications "ResourceType=security-group, Tags=[{Key=Name,Value=umemoto_SG_EFS}]"

EFS用のSGにはEC2からの2049番ポートへのアクセスを許可するルールを追加します。

使用するオプション 設定値 説明
--group-id sg-xxxxx SGのIDを入力
--protocol tcp 説明を入力
--port 2049 アクセスを許可したいプロトコルのポート範囲を入力
--source-group sg-xxxxx EC2用のSGのIDを入力

入力

aws ec2 authorize-security-group-ingress `
    --group-id sg-xxxxx `
    --protocol tcp `
    --port 2049 `
    --source-group  sg-xxxxx

出力

{
    "Return": true,
    "SecurityGroupRules": [
        {
            "SecurityGroupRuleId": "sgr-xxxxx",
            "GroupId": "sg-xxxxx",
            "GroupOwnerId": "xxxxx",
            "IsEgress": false,
            "IpProtocol": "tcp",
            "FromPort": 2049,
            "ToPort": 2049,
            "ReferencedGroupInfo": {
                "GroupId": "sg-xxxxx"
            }
        }
    ]
}

最後に、RDS用のSGを作成していきます。

使用するオプション 設定値 説明
--group-name umemoto_SG_RDS 設定したいグループネームを入力
--description "dedicated to umemoto RDS" 説明を入力
--vpc-id vpc-xxxxx VPCのIDを入力
--tag-specifications  "ResourceType=security-group,
Tags=[{Key=Name,Value=umemoto_SG_RDS}]"
SGに対しネームタグを追加

入力

aws ec2 create-security-group `
    --group-name umemoto_SG_RDS `
    --description "dedicated to umemoto RDS" `
    --vpc-id vpc-xxxxx `
    --tag-specifications "ResourceType=security-group, Tags=[{Key=Name,Value=umemoto_SG_RDS}]"

RDS用のSGにはMYSQL/Auroraを選んでEC2からの3306番ポートへのアクセスを許可します。

使用するオプション 設定値 説明
--group-id sg-xxxxx SGのIDを入力
--protocol tcp 説明を入力
--port 3306 アクセスを許可したいプロトコルのポート範囲を入力
--source-group sg-xxxxx EC2用のSGのIDを入力

入力

aws ec2 authorize-security-group-ingress `
    --group-id sg-xxxxx `
    --protocol tcp `
    --port 3306 `
    --source-group  sg-xxxxx

出力

{
    "Return": true,
    "SecurityGroupRules": [
        {
            "SecurityGroupRuleId": "sgr-xxxxx",
            "GroupId": "sg-xxxxx",
            "GroupOwnerId": "xxxxx",
            "IsEgress": false,
            "IpProtocol": "tcp",
            "FromPort": 3306,
            "ToPort": 3306,
            "ReferencedGroupInfo": {
                "GroupId": "xxxxx"
            }
        }
    ]
}

これですべてのセキュリティグループの作成を完了しました。

5.疎通確認

ここまで出来たらVPC内にEC2用のSGをアタッチしたEC2を起動させて疎通確認を行います。
EC2インスタンス作成はこちらの記事を参考にして行います。

EC2作成には、[aws ec2 run-instances]コマンドを使用します。

使用するオプション 設定値 説明
--image-id ami-0cbec04a61be382d9 使用するAMIのIDを入力
--count 1 使用するEI アクセラレータ数を指定
--instance-type t2.micro 使用するインスタンスタイプを指定
--key-name umemoto_kadai_1 先ほど作成したキーネームを入力
--security-group-ids sg-xxxxx 作成したEC2用のSGのIDを入力
--subnet-id subnet-xxxxx 使用するパブリックサブネットを入力
--private-ip-address 10.0.1.50 意思疎通テストなので構成図に設定したIP以外を入力
--capacity-reservation-specification CapacityReservationPreference=none キャパシティの予約をオフに
--tag-specifications "ResourceType=instance, Tags=
[{Key=Name,Value=connectivity-test}]"
タグを設定

入力

aws ec2 run-instances `
    --image-id ami-0cbec04a61be382d9 `
    --count 1 `
    --instance-type t2.micro `
    --key-name umemoto_kadai_1 `
    --security-group-ids sg-xxxxx `
    --subnet-id subnet-xxxxx `
    --private-ip-address 10.0.1.50 `
    --capacity-reservation-specification CapacityReservationPreference=none `
    --tag-specifications "ResourceType=instance, Tags=[{Key=Name,Value=connectivity-test }]"

出力

{
    "Groups": [],
    "Instances": [
        {
            "AmiLaunchIndex": 0,
            "ImageId": "ami-xxxxx",
            "InstanceId": "i-xxxxx",
            "InstanceType": "t2.micro",
            "KeyName": "umemoto_kadai_1",
            "LaunchTime": "2022-05-19T06:54:05+00:00",
            "Monitoring": {
                "State": "disabled"
            },
            "Placement": {
                "AvailabilityZone": "ap-northeast-2a",
                "GroupName": "",
                "Tenancy": "default"
            },
            "PrivateDnsName": "ip-10-0-1-50.ap-northeast-2.compute.internal",
            "PrivateIpAddress": "10.0.1.50",
            "ProductCodes": [],
            "PublicDnsName": "",
            "State": {
                "Code": 0,
                "Name": "pending"
            },
            "StateTransitionReason": "",
            "SubnetId": "subnet-xxxxx",
            "VpcId": "vpc-xxxxx",
            "Architecture": "x86_64",
            "BlockDeviceMappings": [],
            "ClientToken": "xxxxx-xxxxx-xxxx-xxxxx",
            "EbsOptimized": false,
            "EnaSupport": true,
            "Hypervisor": "xen",
            "NetworkInterfaces": [
                {
                    "Attachment": {
                        "AttachTime": "2022-05-19T06:54:05+00:00",
                        "AttachmentId": "eni-attach-xxxxx",
                        "DeleteOnTermination": true,
                        "DeviceIndex": 0,
                        "Status": "attaching",
                        "NetworkCardIndex": 0
                    },
                    "Description": "",
                    "Groups": [
                        {
                            "GroupName": "umemoto_SG_EC2",
                            "GroupId": "sg-xxxxxb"
                        }
                    ],
                    "Ipv6Addresses": [],
                    "MacAddress": "xxxxx",
                    "NetworkInterfaceId": "eni-xxxxx",
                    "OwnerId": "xxxxx",
                    "PrivateDnsName": "ip-10-0-1-50.ap-northeast-2.compute.internal",
                    "PrivateIpAddress": "10.0.1.50",
                    "PrivateIpAddresses": [
                        {
                            "Primary": true,
                            "PrivateDnsName": "ip-10-0-1-50.ap-northeast-2.compute.internal",
                            "PrivateIpAddress": "10.0.1.50"
                        }
                    ],
                    "SourceDestCheck": true,
                    "Status": "in-use",
                    "SubnetId": "subnet-xxxxx",
                    "VpcId": "vpc-xxxxx",
                    "InterfaceType": "interface"
                }
            ],
            "RootDeviceName": "/dev/xvda",
            "RootDeviceType": "ebs",
            "SecurityGroups": [
                {
                    "GroupName": "umemoto_SG_EC2",
                    "GroupId": "sg-xxxxx"
                }
            ],
            "SourceDestCheck": true,
            "StateReason": {
                "Code": "pending",
                "Message": "pending"
            },
            "Tags": [
                {
                    "Key": "Name",
                    "Value": "connectivity-test"
                }
            ],
            "VirtualizationType": "hvm",
            "CpuOptions": {
                "CoreCount": 1,
                "ThreadsPerCore": 1
            },
            "CapacityReservationSpecification": {
                "CapacityReservationPreference": "none"
            },
            "MetadataOptions": {
                "State": "pending",
                "HttpTokens": "optional",
                "HttpPutResponseHopLimit": 1,
                "HttpEndpoint": "enabled",
                "HttpProtocolIpv6": "disabled",
                "InstanceMetadataTags": "disabled"
            },
            "EnclaveOptions": {
                "Enabled": false
            },
            "PrivateDnsNameOptions": {
                "HostnameType": "ip-name",
                "EnableResourceNameDnsARecord": false,
                "EnableResourceNameDnsAAAARecord": false
            },
            "MaintenanceOptions": {
                "AutoRecovery": "default"
            }
        }
    ],
    "OwnerId": "xxxxx",
    "ReservationId": "r-xxxxx"
}

作成出来たら疎通確認をします。

SSHはMYIPを受け入れているため成功しますが、HTTPはALBからの通信以外は失敗するはずです。
まずPowerShellで以下のコマンドを利用してSSHの疎通を確認します。

Test-NetConnection [作成したEC2のパブリックIPv4] -port 22

成功しました。
file

次にPowerShellで以下のコマンドを利用してHTTPの疎通を確認します。

Test-NetConnection [作成したEC2のパブリックIPv4] -port 80

予測通り失敗しました。
file

これで作成したEC2のSGが正常に動作していることを確認できました。

6.感想

計4つのセキュリティグループを作成するのは少し大変でしたが良い経験になりました。
CLIは名前の通りコマンドを使用して構築しますが、セキュリティグループに関しては慣れればマネージメントコンソールよりも設定しやすいと思いました。

7.参照

AWS CLI Command Reference
https://docs.aws.amazon.com/cli/latest/reference/ec2/index.html#cli-aws-ec2

Last modified: 2022-05-25

Author