ちょっと話題の記事

PiculetでAWSのセキュリティグループをマイグレーションする

2013.10.25

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

ども、大瀧です。
AWSのセキュリティグループの設定はちょっとした間違いがサービス停止に直結するクリティカルなものなので、本番環境への適用にはかなり気を使うと思います。今回は、そんなセキュリティグループの設定を強力にサポートするPiculetというツールをご紹介します。

概要

Piculetは、弊社ブログで以前ご紹介したRoadworkerと同じGenki Sugawaraさんが開発する、セキュリティグループの設定をRuby DSLで管理できるコマンドラインツールです。

Ruby DSLでセキュリティグループを記述できるので、日々のセキュリティグループの運用をgitなどと組み合わせてコードベースで管理できることが特徴です。なお、今回はバージョン0.1.4で検証しています。

セキュリティグループのマイグレーションとは

AWSのセキュリティグループは、AWSの以下の単位で別々に作成、管理します。

  • AWSアカウント
  • リージョン
  • VPC

ある環境で作り込んだセキュリティグループの設定を他の環境で使い回す、例えば以下のようなケースがあります。

  • 本番用AWSアカウントと開発用AWSアカウントを分けていて、開発用で作ったセキュリティグループと同じものを本番用にも作成したい。
  • BCP対策で、東京リージョンと同じセキュリティグループをシンガポールリージョンに作りたい。

この辺りはCloudFormationが得意とするところなのですが、CloudFormationを導入していない場合や手組みでセキュリティグループが作成済みの場合に、Piculetが活用できます。

インストール、準備

Piculetは、Rubyのライブラリ管理ツールであるgemでインストールします。rbenv環境の方は、rbenv rehashを忘れずに。

$ gem install piculet --no-ri --no-rdoc
Fetching: piculet-0.1.4.gem (100%)
Successfully installed piculet-0.1.4
1 gem installed

piculetコマンドで実行します。引数なしで実行すると、ヘルプが表示されます。

$ piculet
Usage: piculet [options]
    -k, --access-key ACCESS_KEY
    -s, --secret-key SECRET_KEY
    -r, --region REGION
    -a, --apply
    -f, --file FILE
        --dry-run
    -e, --export
    -o, --output FILE
        --split
    -t, --test
        --no-color
        --debug
$

PiculetからAWS APIにアクセスするためのアクセスキー、シークレットキーは以下のいずれかの形式に対応しています。IAM Roleにも対応済み?(未確認)

  • コマンド実行時のオプション
  • 環境変数

アクセスキー、シークレットキーを事前に作成および設定しておきましょう。今回はマイグレーションの対象として、あるAWSアカウントから別のAWSアカウントにセキュリティグループの設定を適用してみます。複数のアクセスキーおよびシークレットキーを扱うので、コマンド実行時のオプションを使用します。

コマンド実行時のオプションにキーを指定するとコマンドログにキーが残ることに注意しましょう。

マイグレーション手順

Roadworkerを使ったことのある方であれば、DSLを記述するデフォルトのファイル名がGroupfileになることを除き、使い方はほぼ同じです。主なオプションを以下に示します。

-r(--region) リージョン名
リージョンを指定します
-e(--export)
セキュリティグループの設定を標準出力にエクスポートします
-o(--output) ファイル名
エクスポートするファイル名を指定します
-a(--apply)
Groupfileの設定をAWSに適用します。
--dry-run
AWSへの適用は行わず、適用内容のみ出力します。

まずは、移行元のAWSアカウントのセキュリティグループ設定をエクスポートします。-e(--export)オプションで、現在のセキュリティグループの設定を標準出力に出力します。-o(--output)オプションもしくはリダイレクトでGroupfileに保存しましょう。

$ piculet -e -k AKIAXXXXXXXXXXXX -s XXXXXXXXXXXXXXXXXXXXXXXX -r ap-northeast-1 > Groupfile

Groupfileの例

# Export SecurityGroup
ec2 "vpc-XXXXXXXX" do
  security_group "default" do
    description "default VPC security group"

    ingress do
      permission :any do
        groups(
          "default"
        )
      end
    end

    egress do
      permission :any do
        ip_ranges(
          "0.0.0.0/0"
        )
      end
    end
  end

  security_group "ssh" do
    description "Enable SSH access via port 22"

    ingress do
      permission :tcp, 22..22 do
        ip_ranges(
          "1.1.1.1/32",
          "2.2.2.2/32"
        )
      end
    end

    egress do
      permission :any do
        ip_ranges(
          "0.0.0.0/0"
        )
      end
    end
  end

  security_group "web" do
    description "web"

    ingress do
      permission :tcp, 80..80 do
        ip_ranges(
          "0.0.0.0/0"
        )
      end
    end

    egress do
      permission :any do
        ip_ranges(
          "0.0.0.0/0"
        )
      end
    end
  end

  security_group "mysql" do
    description "mysql"

    ingress do
      permission :tcp, 3306..3306 do
        groups(
          "web"
        )
      end
    end
    egress do
      permission :any do
        ip_ranges(
          "0.0.0.0/0"
        )
      end
    end
  end
end

今回はマイグレーションが目的なのでDSLの書式の解説は省略しますが、手作業のときに煩雑になりがちなグループID(sg-XXXXXXXX)の指定に70行目のようにグループ名(webなど)が使えるところがとてもスマートで素敵です。

移行先のAWSアカウントのVPC IDに書き換えます。

# Export SecurityGroup
ec2 "vpc-YYYYYYYY" do
(以下略)

準備ができたら、--dry-runオプションで事前に適用内容を確認すると良いでしょう。

$ piculet -a --dry-run -k AKIAYYYYYYYYYYYY -s YYYYYYYYYYYYYYYYYYYYYYYY -r ap-northeast-1
Apply `Groupfile` to SecurityGroup (dry-run)
Create SecurityGroup: vpc-YYYYYYYY > ssh (dry-run)
[WARN] `egress any 0.0.0.0/0` is implicitly defined (dry-run)
Create SecurityGroup: vpc-YYYYYYYY > web (dry-run)
[WARN] `egress any 0.0.0.0/0` is implicitly defined (dry-run)
Create SecurityGroup: vpc-YYYYYYYY > mysql (dry-run)
[WARN] `egress any 0.0.0.0/0` is implicitly defined (dry-run)
Create Permission: classic > /ssh(ingress) > tcp 22..22 (dry-run)
  authorize 1.1.1.1/32, 2.2.2.2/32 (dry-run)
Create Permission: classic > /web(ingress) > tcp 80..80 (dry-run)
  authorize 0.0.0.0/0 (dry-run)
Create Permission: classic > /mysql(ingress) > tcp 3306..3306 (dry-run)
  authorize web (dry-run)
No change
$

では、移行先のAWSアカウントに適用します。

$ piculet -a -k AKIAYYYYYYYYYYYY -s YYYYYYYYYYYYYYYYYYYYYYYY -r ap-northeast-1
Create SecurityGroup: vpc-YYYYYYYY > ssh
Create SecurityGroup: vpc-YYYYYYYY > web
Create SecurityGroup: vpc-YYYYYYYY > mysql
Create Permission: vpc-YYYYYYYY > ssh(ingress) > tcp 22..22
  authorize 1.1.1.1/32, 2.2.2.2/32
Create Permission: vpc-YYYYYYYY > web(ingress) > tcp 80..80
  authorize 0.0.0.0/0
Create Permission: vpc-YYYYYYYY > mysql(ingress) > tcp 3306..3306
  authorize web
$

Management Consoleでセキュリティグループの画面を表示してみます。

sg01

できてますね!

(参考)日々の運用での--dry-runオプションの活用

今回はマイグレーションの例として紹介しましたら、日々の運用でPiculetを利用する際には--dry-runオプションがとても便利です。--dry-runオプションはGroupfileの適用テストを実行しますが、出力として現在のセキュリティグループ設定との差分を表示してくれるので、勝手にセキュリティグループの設定が変わっていないかどうかのチェックに利用することができます。

「ちょっとアプリケーションをメンテナンスしたいので、SSHのポート空けますね」と言って設定を変えたあと、戻すのを忘れていた!なーんて経験、一度はあるんじゃないでしょうか。
そんなチェック漏れを見つけるために使えます。

まとめ

セキュリティグループの設定ツール、Piculetを紹介しました。CloudFormationを導入していない環境であれば、かなり便利に活用できる有用なツールです。弊社の実案件でも、開発環境から本番環境にセキュリティグループの設定を移行するために活用しています。少しでも楽して、AWSを管理していきましょう!