前前回、AWS ConfigやSystems Managerの準備をしました
前回、Ownerタグの有無を自動検出し、EC2にOwnerタグが付与されていない場合にインスタンスを自動停止する設定を行いました
今回は、セキュリティグループのインバウンドルールに、SSH(22),RDP(3389)で、HTTP(80)、HTTPS(443)で、ソースIP 0.0.0.0/0からの通信が許可されているか(=インターネットから全許可か)自動検出します。また自動検出後にセキュリティグループの該当行を自動削除する設定を行います
設定の流れ
- System Managerで、「オートメーション」の「ドキュメント:Custom-AWS-DisablePublicAccessForSecurityGroup」を作成
- AWS Configで、ルール「restricted-common-ports」を作成する中で、自動検出したいポート番号を指定
- 作成したルール「restricted-common-ports」の修復アクションとして、最初に作成した「ドキュメント:Custom-AWS-DisablePublicAccessForSecurityGroup」を指定する
- 動作確認
- セキュリティグループの、インバウンドルールに、自動削除対象のSSH(22),RDP(3389)で、HTTP(80)、HTTPS(443)で、ソースIP 0.0.0.0/0からの通信を許可する設定を行う
- しばらく待って、自動削除対象が削除され、他の設定が削除されていないことを確認する
補足
SSH(22),RDP(3389)を自動検出したい場合、ググると「restricted-ssh」を使う情報をよく見かけました。
しかし、2023/12/16現在、restricted-sshは大阪リージョンで使えません。
今回は「restricted-ssh」を使わず、大阪リージョンでも実装可能な「restricted-common-ports」を使用する設定手順を記載します
最初に、SystemManagerで「オートメーション」の「ドキュメント:Custom-AWS-DisablePublicAccessForSecurityGroup」を作成
セキュリティグループに、IPアドレス範囲 0.0.0.0/0かつポート番号 SSH(22)やRDP(3389)など、危険な設定が存在する場合に、AWSに用意されているAPI: 「RevokeSecurityGroupIngress」を呼び出し、当該セキュリティグループの設定行を削除するためのJSONコードです。
上のスクリーンショットの左側の全ソースコードを、以下に記載しました。
JSONコードを入力したり変更すると、上のスクリーンショットの右側のフロー図に反映され、コードを見るより流れがわかりやすいです。
jsonソース
{
"description": "Disable SSH and RDP ports opened to IP address specified, or to all addresses if no address is specified. Similar to the [RevokeSecurityGroupIngress](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_RevokeSecurityGroupIngress.html ) API, the security group must have existing rules specifically on the SSH and RDP ports in order for ingress to be disabled.",
"schemaVersion": "0.3",
"assumeRole": "{{ AutomationAssumeRole }}",
"parameters": {
"GroupId": {
"type": "String",
"description": "(Required) Security Group ID",
"allowedPattern": "^([s][g]\\-)([0-9a-f]){1,}$"
},
"IpAddressToBlock": {
"type": "String",
"description": "(Optional) Additional Ipv4 or Ipv6 address to block access from (ex:1.2.3.4/32)",
"allowedPattern": "(^$)|^((25[0-5]|(2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3})|(^((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)::((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?))|(^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}))\\/(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)$",
"default": ""
},
"AutomationAssumeRole": {
"type": "String",
"description": "(Optional) The ARN of the role that allows Automation to perform the actions on your behalf.",
"default": ""
}
},
"mainSteps": [
{
"name": "CustomIpCheck",
"action": "aws:branch",
"inputs": {
"Choices": [
{
"NextStep": "DisableSSHFromCustomIpV6",
"And": [
{
"Not": {
"Variable": "{{IpAddressToBlock}}",
"StringEquals": ""
}
},
{
"Variable": "{{ IpAddressToBlock }}",
"Contains": ":"
}
]
},
{
"NextStep": "DisableSSHFromCustomIpV4",
"And": [
{
"Not": {
"Variable": "{{IpAddressToBlock}}",
"StringEquals": ""
}
},
{
"Not": {
"Variable": "{{ IpAddressToBlock }}",
"Contains": ":"
}
}
]
}
],
"Default": "DisableSSHFromIpV4"
}
},
{
"name": "DisableSSHFromIpV4",
"action": "aws:executeAwsApi",
"nextStep": "DisableHTTPFromIpV4",
"isEnd": false,
"onFailure": "step:DisableHTTPFromIpV4",
"inputs": {
"Service": "ec2",
"Api": "RevokeSecurityGroupIngress",
"GroupId": "{{GroupId}}",
"IpPermissions": [
{
"IpProtocol": "tcp",
"FromPort": 22,
"ToPort": 22,
"IpRanges": [
{
"CidrIp": "0.0.0.0/0"
}
]
}
]
}
},
{
"name": "DisableHTTPFromIpV4",
"action": "aws:executeAwsApi",
"nextStep": "DisableHTTPSFromIpV4",
"isEnd": false,
"onFailure": "step:DisableHTTPSFromIpV4",
"inputs": {
"Service": "ec2",
"Api": "RevokeSecurityGroupIngress",
"GroupId": "{{GroupId}}",
"IpPermissions": [
{
"IpProtocol": "tcp",
"FromPort": 80,
"ToPort": 80,
"IpRanges": [
{
"CidrIp": "0.0.0.0/0"
}
]
}
]
}
},
{
"name": "DisableHTTPSFromIpV4",
"action": "aws:executeAwsApi",
"nextStep": "DisableSSHFromIpV6",
"isEnd": false,
"onFailure": "step:DisableSSHFromIpV6",
"inputs": {
"Service": "ec2",
"Api": "RevokeSecurityGroupIngress",
"GroupId": "{{GroupId}}",
"IpPermissions": [
{
"IpProtocol": "tcp",
"FromPort": 443,
"ToPort": 443,
"IpRanges": [
{
"CidrIp": "0.0.0.0/0"
}
]
}
]
}
},
{
"name": "DisableSSHFromIpV6",
"action": "aws:executeAwsApi",
"nextStep": "DisableRDPFromIpV4",
"isEnd": false,
"onFailure": "step:DisableRDPFromIpV4",
"inputs": {
"Service": "ec2",
"Api": "RevokeSecurityGroupIngress",
"GroupId": "{{GroupId}}",
"IpPermissions": [
{
"IpProtocol": "tcp",
"FromPort": 22,
"ToPort": 22,
"Ipv6Ranges": [
{
"CidrIpv6": "::/0"
}
]
}
]
}
},
{
"name": "DisableRDPFromIpV4",
"action": "aws:executeAwsApi",
"nextStep": "DisableRDPFromIpV6",
"isEnd": false,
"onFailure": "step:DisableRDPFromIpV6",
"inputs": {
"Service": "ec2",
"Api": "RevokeSecurityGroupIngress",
"GroupId": "{{GroupId}}",
"IpPermissions": [
{
"IpProtocol": "tcp",
"FromPort": 3389,
"ToPort": 3389,
"IpRanges": [
{
"CidrIp": "0.0.0.0/0"
}
]
}
]
}
},
{
"name": "DisableRDPFromIpV6",
"action": "aws:executeAwsApi",
"isEnd": true,
"inputs": {
"Service": "ec2",
"Api": "RevokeSecurityGroupIngress",
"GroupId": "{{GroupId}}",
"IpPermissions": [
{
"IpProtocol": "tcp",
"FromPort": 3389,
"ToPort": 3389,
"Ipv6Ranges": [
{
"CidrIpv6": "::/0"
}
]
}
]
}
},
{
"name": "DisableSSHFromCustomIpV4",
"action": "aws:executeAwsApi",
"nextStep": "DisableRDPFromCustomIpV4",
"isEnd": false,
"onFailure": "step:DisableRDPFromCustomIpV4",
"inputs": {
"Service": "ec2",
"Api": "RevokeSecurityGroupIngress",
"GroupId": "{{GroupId}}",
"IpPermissions": [
{
"IpProtocol": "tcp",
"FromPort": 22,
"ToPort": 22,
"IpRanges": [
{
"CidrIp": "{{ IpAddressToBlock }}"
}
]
}
]
}
},
{
"name": "DisableRDPFromCustomIpV4",
"action": "aws:executeAwsApi",
"isEnd": true,
"inputs": {
"Service": "ec2",
"Api": "RevokeSecurityGroupIngress",
"GroupId": "{{GroupId}}",
"IpPermissions": [
{
"IpProtocol": "tcp",
"FromPort": 3389,
"ToPort": 3389,
"IpRanges": [
{
"CidrIp": "{{ IpAddressToBlock }}"
}
]
}
]
}
},
{
"name": "DisableSSHFromCustomIpV6",
"action": "aws:executeAwsApi",
"nextStep": "DisableRDPFromCustomIpV6",
"isEnd": false,
"onFailure": "step:DisableRDPFromCustomIpV6",
"inputs": {
"Service": "ec2",
"Api": "RevokeSecurityGroupIngress",
"GroupId": "{{GroupId}}",
"IpPermissions": [
{
"IpProtocol": "tcp",
"FromPort": 22,
"ToPort": 22,
"Ipv6Ranges": [
{
"CidrIpv6": "{{ IpAddressToBlock }}"
}
]
}
]
}
},
{
"name": "DisableRDPFromCustomIpV6",
"action": "aws:executeAwsApi",
"isEnd": true,
"inputs": {
"Service": "ec2",
"Api": "RevokeSecurityGroupIngress",
"GroupId": "{{GroupId}}",
"IpPermissions": [
{
"IpProtocol": "tcp",
"FromPort": 3389,
"ToPort": 3389,
"Ipv6Ranges": [
{
"CidrIpv6": "{{ IpAddressToBlock }}"
}
]
}
]
}
}
]
}
AWS Configで、ルール「restricted-common-ports」を作成
確認画面を見て設定内容を保存する
作成したルール「restricted-common-ports」の修復アクションを作成する
修復アクションとして、最初に作成した「SystemManagerドキュメント:Custom-AWS-DisablePublicAccessForSecurityGroup」を指定する
上記のパラメータAutomationAssumeRoleのarnの値は、下記の記事を参照し「SSM用のIAMロールのARNの値」をコピーペースト