AWS / PHP / Python ちょいメモ

amazon web service , PHP, Python を使ったときのメモ。日本語でググってもわからなかった事を中心に。

EC2 SecurityGroup バックアップできる?

これまで管理もなく使うだけ使ってたリージョンがあったので、整理しようと思い立ってやってみました。


背景

本やオンライン見て試行錯誤すると、よくわからないSecurityGoup増えてませんかね?

僕は、増えてました。が、さくっと消せるかというと、後で欲しくなったりと思ってしまい(片付けベタ)。

なんか、バックアップとってから消したいなと思い aws-cli 使ってやってみました。

結論?

バックアップはできたけど、そこから一発リカバリは無理というのが結論。

他に、良い方法あったら、ぜひ教えて下さい〜

準備

Amazon Linux 2 コンテナ上で aws-cli v1 を触って試してみました。

環境構築に興味があれば、コチラなど参照ください。


古いAPIだろうし aws-cli v1 が動けば、たぶん同じ結果になるかと思います。

SecurityGroup を aws-cli にて扱う

EC2 の SecurityGroup なので コマンド的にも aws ec2 に続くサブコマンドを打っていきます。

使うサブコマンド

リファレンスひらいて security-group で検索かけて、今回扱う候補を絞り込む。

  • authorize-security-group-egress
  • authorize-security-group-ingress
  • create-security-group
  • describe-security-groups

describe〜 で現在の設定を取得しバックアップ。

できれば、それをつかって create〜 と authorize〜 でリカバリできたら最高。

ec2 describe-security-groups

何個ぐらいあるかなーってカウント

49個もあったぞ

# aws ec2 describe-security-groups --query "SecurityGroups[*].{Name:GroupName}" | grep Name | wc
     49     109    1652


id指定して個別確認

# aws ec2 describe-security-groups --group-ids sg-903004f8
{
    "SecurityGroups": [
        {
            "IpPermissionsEgress": [
                {
                    "IpProtocol": "-1",
                    "PrefixListIds": [],
                    "IpRanges": [
                        {
                            "CidrIp": "0.0.0.0/0"
                        }
...

全部JSONでバックアップする

# aws ec2 describe-security-groups > ec2_describe-security-groups.json

create & authorize

最初もった甘い考え。

「--group-ids で取得した単一SecurityGroupのJSONを、そのまま create-security-group に流し込んだら、リカバリできたり?」

は、あえなく玉砕(まあ、idとか勝手に指定せんでくれって感じですよね)。

そもそも create する手順を、公式でチェック。

docs.aws.amazon.com


こちらの手順が必要でした。

  1. セキュリティグループを 作成する
    • create-security-group
  2. ルールをセキュリティグループに追加する
    • authorize-security-group-egress
    • authorize-security-group-ingress

JSONケルトン と describe の出力JSON を比較

後述のスケルトンを比較してみたところ、次の結果となり、リカバリ一発じゃいかんのかーと理解。

  • egress と ingress の inputに使うJSON形式が同じ (どちらも "IpPermissions" オブジェクト)
  • しかしdescribe の出力JSONには "IpPermissions" (Ingress用) と "IpPermissionsEgress" が存在する


頭の中で、次の手順までは浮かんだのですが、リカバリするときに作ろうとなりました。

  1. 出力JSON からcreateに使う部分を抽出 (jq で取り出せる)
  2. createして、返り値の group-id を取得しておく
  3. 出力JSON からegress に使う部分を抽出するときに、"IpPermissionsEgress" を "IpPermissions" にリネーム
  4. group-id指定して egress 側のルール追加
  5. 出力JSON からingress に使う部分を抽出する
  6. group-id指定して ingress 側のルール追加

参考 : 出力JSON からcreateに使う部分を抽出 (jq で取り出せる)

出力JSONの中から、create-security-group に必須の3オブジェクトだけ取り出し。

3つのKEYだけほしかったので、key, valueに変換してから絞り込み。

cat sg-903004f8.json  | jq '. | to_entries | map( select(.key | test("(VpcId|GroupName|Description)") )) | from_entries'
{
  "Description": "HTTP/HTTPS Enable",
  "GroupName": "Yano-webserver-sg",
  "VpcId": "vpc-f81c759d"
}

あ with_entries 使えば、もっと簡潔にかけるのか。

たぶん、これで同じ結果かな?

  • cat sg-903004f8.json | jq '. | with_entries( select(.key | test("(VpcId|GroupName|Description)") )'

参考 : JSONケルト

バックアップをJSONで行ってるので、JSONを create & authorizeのINPUT ( --cli-input-json ) に使いたく、スケルトン(雛形?)を確認。

ケルトン : create-security-group

# aws ec2 create-security-group --generate-cli-skeleton 
{
    "Description": "", 
    "GroupName": "", 
    "VpcId": "", 
    "DryRun": true
}

ケルトン : authorize-security-group-egress

# aws ec2 authorize-security-group-egress --generate-cli-skeleton 
{
    "DryRun": true, 
    "GroupId": "", 
    "IpPermissions": [
        {
            "FromPort": 0, 
            "IpProtocol": "", 
            "IpRanges": [
                {
                    "CidrIp": "", 
                    "Description": ""
                }
            ], 
            "Ipv6Ranges": [
                {
                    "CidrIpv6": "", 
                    "Description": ""
                }
            ], 
            "PrefixListIds": [
                {
                    "Description": "", 
                    "PrefixListId": ""
                }
            ], 
            "ToPort": 0, 
            "UserIdGroupPairs": [
                {
                    "Description": "", 
                    "GroupId": "", 
                    "GroupName": "", 
                    "PeeringStatus": "", 
                    "UserId": "", 
                    "VpcId": "", 
                    "VpcPeeringConnectionId": ""
                }
            ]
        }
    ], 
    "CidrIp": "", 
    "FromPort": 0, 
    "IpProtocol": "", 
    "ToPort": 0, 
    "SourceSecurityGroupName": "", 
    "SourceSecurityGroupOwnerId": ""
}

ケルトン : authorize-security-group-ingress

# aws ec2 authorize-security-group-ingress --generate-cli-skeleton 
{
    "CidrIp": "", 
    "FromPort": 0, 
    "GroupId": "", 
    "GroupName": "", 
    "IpPermissions": [
        {
            "FromPort": 0, 
            "IpProtocol": "", 
            "IpRanges": [
                {
                    "CidrIp": "", 
                    "Description": ""
                }
            ], 
            "Ipv6Ranges": [
                {
                    "CidrIpv6": "", 
                    "Description": ""
                }
            ], 
            "PrefixListIds": [
                {
                    "Description": "", 
                    "PrefixListId": ""
                }
            ], 
            "ToPort": 0, 
            "UserIdGroupPairs": [
                {
                    "Description": "", 
                    "GroupId": "", 
                    "GroupName": "", 
                    "PeeringStatus": "", 
                    "UserId": "", 
                    "VpcId": "", 
                    "VpcPeeringConnectionId": ""
                }
            ]
        }
    ], 
    "IpProtocol": "", 
    "SourceSecurityGroupName": "", 
    "SourceSecurityGroupOwnerId": "", 
    "ToPort": 0, 
    "DryRun": true
}

その他

JSON 扱い方はひらめくのだけど、jq 慣れてなくて、思うように進捗出せなかった。

1個2個なら、vi でエディットのほうが早いという。

また今度、トライしてみよう。