AWS Certificate Manager (ACM) のSSL証明書をAWSマネージドサービスを駆使して自動取得するクライアント Certman を作った #fukuokarb

ACMSSL証明書取得が本当に毎回面倒だしすぐ忘れるので、いつもの自分の取得方法をCLIツールにしました。

github.com

前提

SSL証明書が必要なドメインを同一アカウント内のRoute53で管理している必要があります。

インストール

$ gem install certman

使い方

例えば、blog.example.comSSL証明書を取得したいときは certman request blog.example.com を実行します。

最初にいくつかの注意事項に答えるとCertmanがAWSマネージドサービスを駆使してSSL証明書を取得します。

$ certman request blog.example.com
NOTICE! Certman support *us-east-1* only, now. OK? Yes
NOTICE! When requesting, Certman replace Active Receipt Rule Set. OK? Yes
[] [ACM] Check Certificate (successfull)
[] [Route53] Check Hosted Zone (successfull)
[] [Route53] Check TXT Record (successfull)
[] [Route53] Check MX Record (successfull)
[] [S3] Create Bucket for SES inbound (successfull)
[] [SES] Create Domain Identity (successfull)
[] [Route53] Add TXT Record Set to verify Domain Identity (successfull)
[] [SES] Check Domain Identity Status *verified* (successfull)
[] [Route53] Add MX Record Set (successfull)
[] [SES] Create Receipt Rule (successfull)
[] [ACM] Request Certificate (successfull)
[] [S3] Check approval mail (will take about 30 min) (successfull)
[] [SES] Remove Receipt rule (successfull)
[] [Route53] Remove Record Set (successfull)
[] [SES] Remove Verified Domain Identiry (successfull)
[] [S3] Delete Bucket (successfull)
Done.

certificate_arn: arn:aws:acm:us-east-1:0123456789:certificate/123abcd4-5e67-8f90-123a-4567bc89d01

完了までに約30分かかりますが、マネジメントコンソールでポチポチやるよりずっとマシです。

証明書を削除したいときは certman delete コマンドを実行します

$ certman delete blog.example.com
[] [ACM] Delete Certificate (successfull)
Done.

途中で失敗したときのRollbackをもう少しサポートしたいと思いますが、普通に使えるのではないかと思います。

ワイルドカードドメインはまだテストしていません。

というわけで

ACMの取得方法を忘れようと思います。

Ansible徹底入門は"今"のAnsibleの使い方を教えてくれる再入門書籍

Ansible徹底入門 クラウド時代の新しい構成管理の実現

Ansible徹底入門 クラウド時代の新しい構成管理の実現

「Ansible徹底入門 クラウド時代の新しい構成管理の実現」を読了しました。

わたしのAnsibleスペック

とりあえず自分のスペックを。

  • 1.5か1.6から使い始めています。
  • 現在は1.9をメインに使っています。
  • ChefやPuppetはほとんど利用していません。
  • 受託開発をやっているせいか、結構な数のPlaybookを書いてきました。

“今"のAnsibleを教えてくれる

Ansible自体は知っていますし、実際に業務で使っていますが、本書を読んで感じたのは「自分の使い方は古い」ということでした。

古い書き方

私はLAMP環境がメインなのですが、次のプロジェクトに移るとき、過去のRoleを参考にします(「Roleの共有はコードが複雑になるので無理」派です)。

そのせいで書き方が古いままで、また、使い方にクセがあるのだと思います。

今の書き方

例えば、パラメータを = でつなげるのは今は推奨されない書き方だというのも本書のコラムで知りました。block~rescue 構文も使ったことがありませんでした。

もう十分に枯れたと勝手に思っていました。

しかしそんなことはありませんでした。

まさに今のAnsibleを教えてくれます。

チュートリアルとして最適

“徹底入門"というだけあって、Ansibleという構成管理ツールの必要性からしっかり教えてくれます。

1章から4章まで通読すれば、まず実践レベルで使えるようになるのではないでしょうか。5章をチュートリアル的に実施したらもう十分です。

正しくAnsibleの使い方を教えてくれるチュートリアルとして、今の時点でベストだと思います。

会社でも来年度の新人のために1冊購入しました。

次の使い方を模索できる

もともとはAnsibleは「サーバ」に対しての構成管理ツールでしたが、本書を読んでみるとどんどんその幅を広げていることがわかります。

Infrastructure as Codeの時代に、適材適所でツールを利用するのも1つですが、Ansibleに統一することを検討するというのも良いのかもしれません。

6〜8章でOpenStack、AWS、Azureのモジュールの解説やチュートリアルもあるので、本書でまず検討することができます。

特に7章のCFnとの連携、ローリングデプロイのチュートリアルは実践的といえるのではないでしょうか。

Dockerとの連携

Dockerをやっと開発環境の一部として使い始めました。

9章でAnsible Containerの使い方が紹介されています。

Ansibleを開発環境でも本番環境でも使っている自分としては、まずはDockerを開発環境でWith Ansibleで活用して、本番環境でAnsibleだけを利用するという現実的なアプローチが取れそうで期待が高まります。

個人的にはDockerfileを書かなくて生きていけそうなので嬉しいです。

テスト

10章でAnsibleのPlaybookのテスト手法が紹介されています。

個人的にはAnsibleで管理されているサーバにさらにテストを書くのは、(主にコスト面で)懐疑的です。

しかし、本書で紹介されていたのはそれではなくてPlaybook自体のテストでした。

そういえば、チマチマ育てていった結果、いざ順番に実行したらコケるようになったPlaybookがあったなあ、と思い出しました。。。

というわけで

1系のAnsibleに慣れ親しんだ人も、今からAnsibleを使ってみようという人にもオススメです。

最後に

kaz29さん、ご恵投いただきありがとうございました!

Ansibleへの再入門ができた気がします!


久しぶりにansible.elに手を入れてみるかな。。。

awspecのAPIで悩んでいる その2

現在、awspecの各リソースタイプは、リソースの特定にIDか、タグの Name を利用しているます。

しかし、「サーバはペットから家畜へ」と言われるようにAWS上のリソースに名前がつくことのほうが少なくなっているようです。

awspecでもIssueが上がっています。

github.com

awspecとしてはリソースを一意に特定してテストするコンセプトは重要だ思っているので、(そのコンセプトは変えずに)例えば “IDを特定するためのヘルパー” を提供しようと考えています。

ヘルパー名は仮ですが、ec2リソースタイプに対して ec2_filter というヘルパーを用意した場合、以下のような使い方ができるようにしたいのです。

describe ec2(ec2_filter(tags: {'TagKey' => 'TagValue'})) do
   it { sholud be_running }
end

describe ec2(tags: {'TagKey' => 'TagValue'}) do # work ec2_filter() inside
   it { sholud be_running }
end
ec2_filter(tags: {'TagKey' => 'TagValue'}).each |id|
  describe ec2(id) do
     it { sholud be_running }
  end
end

ec2_filter(asg: 'my-asg').each |id|
  describe ec2(id) do
     it { sholud be_running }
  end
end

何に悩んでいるのか

ヘルパーの命名規則(名前)です。

  • おそらく各リソースに対して専用のリソースが必要
  • finder という名前は既に利用
  • 1つのリソースを特定するために使ったり、複数のリソースのIDを取得するために使ったりしたい

どうしたものか。。。

holiday-jp/holiday_jpに内閣府の「国民の祝日」のCSVファイルによるテストを追加しました

日本の祝日のデータセット holiday-jp/holiday_jp内閣府の「国民の祝日」CSVファイルによるテストを追加しました。

Tachikoma.ioによる定期テスト も回っていますので、今後安心して内閣府が定めた国民の祝日が反映されたデータセットが活用できます。

ちなみに

機械的なアクセスについて、内閣府のホームページの利用規約に記載がなかったので、(なんとなく)念の為内閣府に確認をしたところ、(「定期的に週1回、それ以外にもテスト実行する度にアクセス」ということを伝えた上で)

「常識的な範囲であれば機械的なアクセスをしても問題ない」

と回答いただきましたので、このまま利用させていただこうと思います。

awspecのアカウント系のAPIに悩んでいる

追記 (2017/3/10 無事解決。マージしました)

github.com

awspecでアカウントに紐づくような情報のテストが書けるように「いつかやろう」と思っていたら、とうとうそれ系のPull Requestが来てしまったので いよいよ解決しなければならない感じになっています。

後押しされた感じですね。

何が課題なのか

awspecは、AWSのサービスやリソースをIDやNameタグで一意に特定して、それに対してテストケースを書くようなAPIになっています。

例えば、EC2の場合

describe ec2('i-ec12345a') do
  it { should be_running }
end

のようにインスタンスのIDを渡すことでインスタンスを一意に特定して、そのEC2リソースについてのテストを書きます。一意に特定できなかったらエラーになります。

ところが、「VPCの最大数」や「EIPの最大数」などの上限値のチェックや、最近できたAWS Organizationsのチェックなど、awspecを実行したアカウントに紐づくような情報のテストをするようなAPIは提供されていません。

具体的にaws-sdk-rubyでいうと

  • Aws::EC2::Client#describe_account_attributes
  • Aws::RDS::Client#describe_account_attributes
  • Aws::SES::Client#get_send_quota
  • Aws::Organizations::Client#describe_organization
  • Aws::Organizations::Client#list_accounts

などで取得できるような情報のテストです。

違いとしては、これらは特に一意に特定するようなIDやNameタグがもともと必要ないのです。

微妙な違いですが、そもそも他のリソースタイプと同列に扱って良いのかそうでないのか、決め手がありません。

実装のアイデア

今のところ思いついているアイデアは2つです。

追記: アイデア3をいただきました

イデア1

テストしたい情報を別々のリソースタイプとして定義する

describe ec2_attributes do
  its(:max_elastic_ips) { should eq 5 }
  its(:max_instances) { should eq 20 }
end

describe ses_send_quota do
  its(:max_24_hour_send) { should eq 200.0 }
  its(:max_send_rate) { should eq 1.0 }
  its(:sent_last_24_hours) { should eq 1.0 }
end

describe organization do
  its(:id) { should eq 'o-exampleorgid' }  
  its(:arn) { should eq 'arn:aws:organizations::111111111111:organization/o-exampleorgid' }  
  it { should have_account('222222222222') }
end

イデア2

アカウントとAWS Organizationsの2つにわけて、リソースタイプを定義する

describe account do # or account_attributes
  its('ec2.max_elastic_ips') { should eq 5 }
  its('ec2.max_instances') { should eq 20 }
  its('ses_send_quota.max_24_hour_send') { should eq 200.0 }
  its('ses_send_quota.max_send_rate') { should eq 1.0 }
  its('ses_send_quota.sent_last_24_hours') { should eq 1.0 }
end

describe organization do
  its(:id) { should eq 'o-exampleorgid' }  
  its(:arn) { should eq 'arn:aws:organizations::111111111111:organization/o-exampleorgid' }  
  it { should have_account('222222222222') }
end

イデア3 ( from @inokara )

account_attributeに引数を与えることでネストを防ぐ(おそらくアイデア2と共存可能)

describe account_attribute('ses_send_quota') do
  its(:max_24_hour_send) { should eq 200.0 }
  its(:max_send_rate) { should eq 1.0 }
  its(:sent_last_24_hours) { should eq 1.0 }
end

今のところアイデア2のほうが使う側としては直感的かなーとは思っているのですが、決め手がなく悩んでいるところ。

うーん。

家庭内Slackと家庭内Backlogを連携させたかったので、backslackを作った

もう様々なところでやり尽くした感のあるツールです。

f:id:k1LoW:20170301193718p:plain

github.com

なぜ作ったのか

実は、F社には既に同様のサービスが稼働していて、便利に使わせてもらっています。

ただ、今回連携したかったのが 家庭内 のものだったので、そのまま流用するわけにはいかないかなーと思ったのと、Qiitaのエントリ はあるけどソースが公開されていなかったので、作りました。

使い方

使い方は README にあるとおりなのですが、

  1. backslackをデプロイ (エンドポイントのURLを取得)
  2. SlackのIncoming webhook URLを取得

これだけで初期構築は完了で、あとはBacklogにWebhookを追加するだけでOKです。

https://x0x1x2x3x.execute-api.ap-northeast-1.amazonaws.com/v0/hook?space=myspace&webhook_url=https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX&channel=general

ポイントは、必要な設定をURLのクエリパラメータに入れてしまうことで、あとはbackslackを放置できるところ。

faultlineと同じように POST with config の考え方です。

Backlogのスペースをまたいでも、プロジェクトをまたいでも、Slackチームをまたいでもいくらでも連携できますし、設定いらずなので便利。

というわけで

もし、まだBacklogとSlackを連携していないご家庭がありましたら是非ご利用下さい。

"キーレスエントリ"なスキーマに、テンポラリな外部キーを設定するツール tmpfk を作った

細かすぎて伝わらないツールだ。。。

f:id:k1LoW:20170227204834p:plain

キーレスエントリなスキーマ

SQLアンチパターン に「外部キー嫌い(キーレスエントリ)」というのがあります。

外部キー制約(FOREIGN KEY)の設定をしないデータベース設計です。

(最近の)Ruby on Railsはどうなのかわかりませんが、

例えばCakePHPだと、テーブル名やフィールド名が(Railsと同じ)命名規則に沿っていると外部キーを自動で判定し、bakeしたタイミングで \Cake\ORM\RulesChecker#existsIn() という外部キー制約をサポートするようなコードが生成されます。

そして、そのままキーレスエントリなスキーマで開発が進むことがよくあります。

(ほかにも理由があったりもしますが)

(本エントリでは、キーレスエントリ自身については言及しません)

それでもER図を生成したい

ところで、

Rails/Cakeなエンジニアは、外部キー制約を設定していなくても、命名規則に沿っていればテーブル名やフィールド名を見て外部キーかどうかを判断できます。

しかし、ER図をスキーマからリバースエンジニアリングして生成くれるような世の中の便利ツール がそれらを判定してくれることは少ないです。

rails-erd などでER図を生成できたりはしますが、残念ながら自分の主戦場はRailsではなくCakePHPなのです。( model_info は懐かしい思い出 )

便利なER図生成ツールは使いたい。でも外部キー制約は今ない。

というわけで、

じゃあ、テンポラリに外部キー制約をはっちゃえばいいじゃん。そしてその後外せばいい

というかなり強引なアプローチのためのツールを作りました。

tmpfk

github.com

RailsCakePHP命名規則に沿って外部キーを付けたり外したりするツールです。

必要なもの

インストール

$ gem install tmpfk

使い方

使い方は簡単です。

対象データベースに外部キーを一気につけるコマンド add

$ tmpfk add -c config.yml 

対象データベースからtmpfkでつけた外部キーのみを一気に外すコマンド drop

$ tmpfk drop -c config.yml 

だけです。

簡単だからといって、運用を開始しているデータベースに直接 tmpfk add するのはヤメましょう。 (別途スキーマのみのデータベースを用意するなどしましょう)

ただ、

もし、

「これからも外部キー制約をつけたまま生きていくんだ!」と思ったら --prefix オプションがありますので、ある程度本気度のある外部キー制約名をつけましょう。

$ tmpfk add -c production_config.yml --prefix ore-ha-honki-da_

というわけで

ER図の自動生成をあきらめたキーレスエントリな皆さん。

使ってみて下さい。

$ tmpfk drop -c production_config.yml --prefix ore-ha-honki-da_