HashiCorpの日本語Vaultハンズオンを実施した!
業務でHashiCorpのVaultを使うかもしれないのでハンズオンをやってみた.GitHubに日本語のハンズオン資料が公開されているのでそれをもとに進めた.
ハンズオンアジェンダ
GitHubで公開されている日本語のハンズオンアジェンダを以下に示す.この中にはハンズオンとしての内容がまだ公開されていないものも含まれている.
- 初めてのVault
- Secret Engine 1: Key Value
- Secret Engine 2: Databases
- 認証とポリシー
- Auth Method 1: LDAP
- Auth Method 2: AppRole
- Auth Method 3: OIDC
- Auth Method 4: GitHub
- Response Rapping
- Secret Engine 3: Public Cloud (AWS, Azure, GCP)
- Secret Engine 4: PKI Engine
- Secret Engine 5: Transit (Encryption as a Service)
- Secret Engine 6: SSH
- 運用系機能色々
- CIツール連携(Concourse, Jenkins)
- Kubernetes連携
- Cloud Foundry連携
- Enterprise機能の紹介
今回は初めてVaultに触るので初めてのVault,Secret Engine 1: Key Value,Secret Engine 2: Databases,認証とポリシーの4つをやってみる.具体的な手順はハンズオンに任せるとして,この記事ではそれぞれのハンズオンで学んだことと,自分が思う重要な概念や押さえるべきポイントについてまとめてみようと思う.
1. 初めてのVault
ここではVaultをインストールしてVaultを立ち上げ,あとのハンズオンの準備をしていく.
このハンズオンで学んだこと
- Vaultのインストール
- Vaultサーバの立ち上げ(開発モード)
- シークレットエンジン
- シークレットの保存・取得
- Vaultサーバの立ち上げ(本番モード)
- Vaultの初期化処理
シークレットエンジン
シークレットエンジンとはkey=valueでデータを格納・生成・暗号化するVaultのコンポーネントである. AWSのIAMのキーやDatabaseへアクセスするシークレットなどさまざまな用途で使えるように,Vaultで専用のコンポーネントが用意されている.例えばkv
シークレットエンジンを新規で使う時はvault secrets enable -path=kv kv
のようにシークレットエンジンを有効にする.さらに,パスを指定してエンドポイントにみたてて,以後そのエンドポイントに操作を実行するのが特徴である.用途にあったシークレットエンジンを使うことでシークレットを適切に扱うことが可能となる.
Vaultの初期化処理
本番モードのVaultではセキュアな設計がされているので,起動直後はsealed
という状態になっておりVaultへログインできない.ログインするにはinit
とunseal
という初期化処理が必要になる.まずinit
処理をする.
$ vault operator init Unseal Key 1: JLYUBHrdwWu2dxwjCazqsCQ4OJPJtiMFsIZeO1osyJ1t Unseal Key 2: nEjGt+rYSOomqmyTsuF7PnKPS+NE3yPEfuo6WDXm/QDR Unseal Key 3: d5nTCzEGKIBPFGCC3ANzKf8gGgwoV8APr6V9KdDcNjOW Unseal Key 4: sd7vzV1FQk/96xQmIuKRKhydy9tGEmORbFyozAKxFc4n Unseal Key 5: JqLGxcvA3gLrwQHIliWvl1ytkMbuDGu/6p2KzGpvnCa9 Initial Root Token: s.Wi5WjPfPHqbFAcXjwsDCHQLd ~~~
init
の処理をすると,Vaultをunseal
するためのUnseal Key
とInitial Root Token
が生成される.試しにこの状態でRoot Token
を使ってログインしてみる.
$ vault login Token (will be hidden): Error authenticating: error looking up token: Error making API request. URL: GET http://127.0.0.1:8200/v1/auth/token/lookup-self Code: 503. Errors: * error performing token check: Vault is sealed
エラーになる.Vaultではsealed
状態になっているといかに強力な権限のあるトークンを使ったとしても操作は受け付けない.unseal
の処理はUnseal Key
を使う.デフォルトだと5つのキーが生成され,そのうち3つのキーが集まるとunsealされる.このアルゴリズムはシャミアの秘密鍵分散法と呼ばれる.3つのUnseal Key
を入れてみる.
$ vault operator unseal Unseal Key (will be hidden): Key Value --- ----- Seal Type shamir Initialized true Sealed true Total Shares 5 Threshold 3 Unseal Progress 1/3 Unseal Nonce 32d20912-88dd-16e2-28d3-87344abec5fc Version 1.2.3 HA Enabled false $ vault operator unseal Unseal Key (will be hidden): Key Value --- ----- Seal Type shamir Initialized true Sealed true Total Shares 5 Threshold 3 Unseal Progress 2/3 Unseal Nonce 32d20912-88dd-16e2-28d3-87344abec5fc Version 1.2.3 HA Enabled false $ vault operator unseal Unseal Key (will be hidden): Key Value --- ----- Seal Type shamir Initialized true Sealed false Total Shares 5 Threshold 3 Version 1.2.3 Cluster Name vault-cluster-7815e4aa Cluster ID 12747d60-78d3-8fad-6082-102052ac8c74 HA Enabled false
これでログインができる.
$ vault login s.Wi5WjPfPHqbFAcXjwsDCHQLdToken (will be hidden): Success! You are now authenticated. The token information displayed below is already stored in the token helper. You do NOT need to run "vault login" again. Future Vault requests will automatically use this token. Key Value --- ----- token s.Wi5WjPfPHqbFAcXjwsDCHQLd token_accessor NX8h0laChNLO5oObu2nDtovT token_duration ∞ token_renewable false token_policies ["root"] identity_policies [] policies ["root"]
やや面倒なこの仕組みの何が嬉しいのかということについては以下のブログが参考になった.
2. Secret Engine 1: Key Value
ここではシンプルなKeyValueStore型のシークレットエンジンを使ってデータのCRUD
をするハンズオンを行う.
このハンズオンで学んだこと
- Key Value Store型のシークレットエンジン
- データの
CRUD
- データのバージョニング管理
- 2つのデータ更新パターン
- データの
3. Secret Engine2: Databases
ここではMySQLとVaultを使い,Vaultで発行したシークレットを用いてMySQLにアクセスするハンズオンを行う.
このハンズオンで学んだこと
- Databaseのシークレットエンジン
- Vaultが対応しているDatabaseシークレットエンジン一覧
- Cassandra
- Influxdb
- HanaDB
- MongoDB
- MSSQL
- MySQL/MariaDB
- PostgreSQL
- Oracle
- VaultがMySQLの操作を制限するようなロールを作成し,そのロールの内容に基づいてVaultがアプリケーションへシークレットを生成する流れ
- 動的シークレットの破棄
- Rootユーザのパスワードローテーション
MySQLへのアクセスの流れ
以下の図のような流れでアプリケーションはMySQLへのアクセスを実現する.
それぞれのステップをみていく.
① Vaultに特権ユーザのクレデンシャルとデータベースの接続先を登録する.MySQLのroot
ユーザ(特権ユーザ)を指定してコネクションの設定をする.②で作成するロールもここで指定しておく必要がある.また,ロールは複数指定できる.
$ vault write database/config/mysql-handson-db \ plugin_name=mysql-legacy-database-plugin \ connection_url="{{username}}:{{password}}@tcp(127.0.0.1:3306)/" \ allowed_roles="role-handson" \ username="root" \ password="rooooot"
② MySQLへの権限やシークレットのTTLを記述したロールを定義する
$ vault write database/roles/role-handson \ db_name=mysql-handson-db \ creation_statements="CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}';GRANT SELECT ON *.* TO '{{name}}'@'%';" \ default_ttl="1h" \ max_ttl="24h"
③ クライアントからVaultに対してシークレットの発行を依頼する
$ vault read database/creds/role-handson Key Value --- ----- lease_id database/creds/role-handson/G3tJu3gN8nGoL8Z8MlVkvD2g lease_duration 1h lease_renewable true password A1a-qIpUomJUoXOiHlQh username v-role-PaKXo1BO1
④ 取得したシークレットでMySQLにアクセス
$ mysql -u v-role-PaKXo1BO1 -p -h 127.0.0.1 Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 9 Server version: 5.7.22 MySQL Community Server (GPL) Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. $ mysql>
⑤ ロールによりSelectはできるがInsertはできないことを確認する.
$ mysql> select * from products; +------+-------------+-------+ | id | name | price | +------+-------------+-------+ | 1 | Nice hoodie | 1580 | +------+-------------+-------+ 1 row in set (0.00 sec) $ mysql> insert into products (id, name, price) values (2, "hoge", 1600); ERROR 1142 (42000): INSERT command denied to user 'v-role-PaKXo1BO1'@'127.0.0.1' for table 'products'
動的シークレットの破棄
ロールにシークレットのTTLを設定できる.TTLを過ぎれば当該シークレットではMySQLにログインできなくなる.またrevoke
処理で発行したシークレットを明示的に無効にできる.再びMySQLにログインしたい場合は,再度シークレットを発行するか,シークレットのTTLが切れる前にrenew
処理と呼ばれるTTLを延長する処理のどちらかを実行すればよい.
Rootユーザのパスワードローテーション
VaultにMySQLの特権を持たせているためそのパスワードの扱いが非常にセンシティブである.Vaultにはコンフィグレーションとして登録したデータベースのパスワードをローテーションさせるAPIがある.これを使ってこまめにRootのパスワードをリフレッシュできる.ただし,MySQLのRootユーザがVaultに登録してあるもの1つだけだと,Rootユーザのパスワードのローテーションを行った後はRootのパスワードはVaultしか扱うことができない.そのため通常別の特権ユーザをMySQLに準備してから行う.
4. 認証とポリシー
ここではエンドポイントごとにポリシーを設定してトークンを発行し,アクセスコントロールを試してみるハンズオンを行う.
このハンズオンで学んだこと.
- ポリシーの利用方法
ロールとポリシーの違い
ポリシーの作成方法や使い方はハンズオンで十分学ぶことができる.個人的に思うここでの重要なポイントは1つ前のSecret Engine2: Databasesで学んだロールと今回のポリシーの違いだと思う.利用するアプリケーションのアクセスをコントロールをしているという点においては同じだが,ロールとポリシーではコントロールする対象領域が異なる.1つ前のハンズオンを例にとると,ロールの場合コントロールする対象領域はMySQLだった.つまり,MySQLへアクセスするシークレットが発行された上で,そのシークレットでMySQLにログインするアプリケーションにどんな制限を持たせるかというのを定義するのがロールである.一方,ポリシーはVaultのエンドポイントを対象領域としている.例えば,「kv
タイプのとあるエンドポイントにはread
,write
を持たせるけど,database
タイプのエンドポイントにはアクセスさせない」というようなポリシーを定義をする.もしこの例が適用されたトークンが発行されると,たとえロールの設定にすべてのテーブルへのアクセス許可を書いていたとしても,そもそもdatabase
タイプのエンドポイントにアクセスができないのでシークレットが発行されず,MySQLにログインすることすらできない.まとめると,ポリシーはエンドポイント単位でのアクセスコントロールを制御し,ロールはエンドポイントに対応しているSecret Engineの中でもっと細かいアクセスコントロールを制御するものだと思う.
まとめ
- HashiCorpのVaultハンズオンを一部試してみた
- Vaultの日本語ハンズオンはとても分かりやすかった.Vaultが何か分からない方におすすめ!
- 認証を絡めたハンズオンもいくつかあるのでやっていこうと思う.また,この記事を書いている間にもハンズオンが変更されたり増えていたりしたのでまた試してみようと思う.
Configで検知した異常をAWS ChatbotでSlack通知できるようになったってよ
以前自分が書いた記事の最後に,AWS Config(以降Config)で検知した異常をAWS Chatbot(以降Chatbot)を使ってSlackへ通知できるようになったことについて触れたので実際に試してみた.
前提
今回も以前の記事と同様にAmazon Simple Notification Service(以降SNS)とConfigを使うが,それらについては設定済みとする.また,Configで検知するルールは,インバウンドのsshを設定しているセキュリティグループでIPをフルオープンにしていないかをチェックするrestricted-ssh
を使う.SNSやConfigの設定については上記の記事に書いてあるので参考までにご覧いただけたらと思う.
今回使用するChatbotについて公式を引用して説明しておく.公式によるとまだBeta版だそう.
AWS Chatbot は、Slack チャンネルや Amazon Chime チャットルームで AWS のリソースを簡単にモニタリングおよび操作できるようにしてくれるインタラクティブエージェントです。 https://aws.amazon.com/jp/chatbot/
構成
今回の登場人物はConfigとSNS,Chatbot,Slack,Amazon CloudWatch(以降CloudWatch)である. 流れとしてはまずChatbotでSNSとSlackを紐づける.そしてCloudWatchで「Configで検知した異常」をトリガーとして「SNSへ通知する」ルールを設定.以上の設定によりConfigで検知した異常をSlackまで届けることができる.また,今回の構成は以下のように1つのアカウント内で完結する.なお構成図のChatbotがAWS提供のアイコンではないのは,ChatbotがBeta版だからかアイコンを公式からダウンロードできなかったからである...ご了承願いたい.
ChatbotによるSNSとSlackの紐づけ
さっそくChatbotのページで,Slackを選んでchat clientを作成.Slackへのログインが求められるのでログインする.
ここからchat clientの設定に入る.chat clientでは主にSNSに届いたリクエストをどのSlackチャンネルに転送するかを定義する.まずは,最終的に通知するSlackチャンネルを選択する.
次にchat clientに割り当てるロールを設定する.特にこだわらなければデフォルトで設定されている新規作成でOK.
最後に,Slackへ転送されるSNSトピックを選択する.
chat clientを作成が成功した時点でSNSのサブスクリプションにもchat clientが追加されていると思うので,これでSlackとSNS間の設定は終了.
CloudWatchの設定
次に,Configの異常をSNSへ通知するためにCloudWatchを設定する.Configの異常イベントをトリガーにSNSへ通知するCloudWatchのルールを作成する.画面左側では,Configで設定済みのルールに違反したイベントを監視するよう設定している.画面右側では,通知先SNSトピックを設定している.
テスト
ここまでで設定は終わったので実際にテストしてみる.試しにセキュリティグループを任意の場所からsshできるよう設定してみると,少し経ってからSlackへ通知が届く.
まとめ
- ChatbotとSNS,CloudWatchを使ってConfigで検知した異常をSlackへ通知してみた
- Lambdaを使ってもできるがChatbotならコードを書かなくてすむ
- Chatbotは無料だしLambdaを使わない分料金が安くなるかと思ったが,ChatbotだとCloudWatchを使わなければならないので料金はあまり変わらないかもしれない
- Slackへの通知をカスタマイズしたいならLambdaを使った方法,とにかく通知がまずしたいならChatbotを使う方法がいいかもしれない
創業者のMitchellさんが来たHashiCorp Meetupに参加した!
VagrantやConsul,Terraformなどさまざまな有名なプロダクトを開発しているHashiCorp社.その創業者の1人であるMitchell Hashimotoさんの来日に伴うMeetupがあったので参加してきた!
Consul
MitchellさんがConsulの概要やConsul Connectについて話された.
従来のデータセンターであればすべてをVMで作るといったようにシンプルな構成だった.しかし最近は複数データセンターがあり,そこに乗っているプラットフォームがベアメタルKubernetesやVM,クラウドだったりとさまざまで,その間で通信が行われている.さまざまな環境で複雑に絡みあうネットワークでService Registry & discovery,Service Meshを実現するのがConsul.特にService Meshを実現している機能をConsul Connectという.以下Consul Connectの機能説明.
Mesh Gateways
各ネットワークのエッジに置かれるMesh Gateway.詳しくは公式に書いてある.
- 各ネットワークにMesh Gatewayを置くとルーティングができる.ネットワークの違うKubernetesクラスタも通信が可能になる.
- APIからDBはOK,WebからDBはNGなどのルールを書くことができる.
- Mesh Gateway間は暗号化される
Connect Layer7 Feature
L7のオプションが色々設定できる.詳しくは公式に書いてある.
- HTTP Routing
- PathやHeaderに基づいて色々Rewriteできる
- Traffix Splitting
- トラフィックのうち10%をv1のサービス,90%をv2のサービスに流すといったことができる
- Custom Resolution
- 「データセンターにあるサービスのヘルスチェックがうまくいかなかった場合のトラフィックを流す先を指定する」など複雑なルールを作ることができる.
感想
Consul知らなかった勢なのでとても勉強になった.全体を通して,Consulはマルチデータセンターやマルチプラットフォームで動くことが強調されていた気がする.
www.slideshare.net
Ask Mitchell Anything
ここからは自由にMitchellさんに質問できるコーナーだった.事前に集めていた質問とその場で出た質問をいくつかMitchellさんに答えてもらった.
Q1. 仮想化技術,コンテナ技術,マイクロサービス化,デリバリ技術など,インフラ技術は目まぐるしく進化し続けている.インフラ技術の今後にどのような未来を描いているか.
- KubernetesがDockerを意識させなくしているが,Dockerがもう少し前に出てくるような技術が出てくるのではと思う.
Q2. Terraformがv1.0になるために必要なことは何か.
- bugfixが終わればすぐ!
Q3. 「何を製品化するか」を決定する際,うまく進める秘訣はあるか.
- サービスの使う方でもあり.他のサービスと自分のサービスを週単位で使い分け,いいものと悪いものを把握している. 会社が大きくなるほど何を目的としてサービスを作っているのか分からなくなるが,自分は前述のやり方を徹底している.
Q4. HashiCorp社のプロダクトのいくつか(Terraform,Consul,Nomadなど)について,共存も可能であるがKubernetesと比較されることがあると思う.仮に,世の中の全てのITサービスが Kubernetes 上で動く世の中であった場合,各プロダクトの在り方がどう変わってくると思うか.
- マルチクラウド,マルチプラットフォームの考えがあり,Integrationにはあまり意味はなく,色々なサービスをパイプしてサービスを作れればいいと思っている.
Q5. NomadをTerraform CloudのようなPaaSサービスとして展開していくような計画はないか.
- NomadのPaaSサービス化はいいかもしれない.
Q6.技術者兼経営者として,苦労されたことは何か.そしてそれをどう解決したか.また技術者兼経営者としての理想の姿とは何か.
- お客様の使い方と自分の使い方が違ったりすると困る.将来,技術的にはこうしたいっていうのがあっても,お客様が違う使い方をしてるとそれに対応する必要がある.
- パートナーの創業者と,お客様と話す&プロダクト開発を交互に回していていい関係が築けている.
Q7. 趣味は何か.
- パイロットも興味あるので勉強.ゲーム.
Q8. いまつくっているもの,気になっているものを教えて欲しいです
- 教えられないがオープンソースで何か作っている.
Q9. 新しい技術で気になるものは何か.
- 新しい技術はみるけど,それをみてなにができるかを考えることが多い.
Q10. HashiCorp社の従業員数が飛躍的に拡大しているという話を聞いた.HashiCorp社が人を惹きつける最大の魅力は何だと分析されているか.またどのような人材を求めているか.最後に,Mitchellさんが大切にしているもの,自身のコアとなるものは何か.
- HashCorpは社員の500/700くらいがリモートで働いている.リモートも魅力の1つ.
- 大切にしているものはTao of HashiCorpに書いてあることがすべて.
Q11 IstioとConsulの違いは何か.
- Istioは1つのプラットフォームで動かすことを前提としている.Consulは複数のプラットフォームで動く.
- 詳しくは公式に書いてある.
Q12. 当時はHowToとか少ないのにGo言語を選んだのはなぜか.
- プロセスを少なくしたかった.
- Rustは新しすぎた.JavaはJVMが嫌い,
- Cを選びかけたが他のプラットフォーム(WindowsやMac)の違いで動かないことがあったのでGoにした.
- DockerやKubernetesが後から採用したので,先に使ってた自分たちは嬉しく思った.
Q13. リモートで設計などのMTGをするのが難しい.何かいい方法があるか.
- 1年1回は最低会うように予算は取っている.その時に新しい製品などについて話し合う.
- チームごとだと一年に数回会えるようにしている.
- リモートの場合はZoomとかで会議できるようにしている.
感想
自分は仕事でWebサービスを提供しているので競合調査として他社のWebサービスを使う.同じ理由で他社プロダクトを使っているという話を聞いて,従事している仕事が違うと調査するポイントも色々違いそうだなと感じた.
弊社配信基盤を支えるHashiCorp OSS
主に動画コンテンツを扱っているサービスにおいてConsulでキャッシュヒット率をあげたお話をされた.
- 動画配信はトラフィックの負荷がすごいのでキャッシュヒット率を高める必要がある
- コンテンツとユーザが多いDMMではコンテンツごとにCDNやオリジンなどに振り分けるよう設計
- オンプレのキャッシュサーバにアクセス情報がたまるのでConsul Eventで情報を転送
- 最終的にその情報を元にユーザはリダイレクトされ,以後その場所から動画コンテンツを取得するようになる
- キャッシュヒット率が30%程度から80%程度に!
感想
Consul Eventの使い方も参考になったが,何よりキャッシュのヒット率をあげる構成がすごいと思った!
Journey to Terraform Enterprise with upgrading v0.10 to v0.12
Terraformを使っていて顕在化してきた問題をEnterpriseによって解決した話をされた.また,それにともなってTerraformのバージョンを0.10から0.12にあげた時の苦労話もされた.
以下の3つの問題を解決するためにTerraform Enterpriseを採用
- 11人で70ものAWSアカウントをTerraformで管理しており,あるアカウント内のメンバーが他のアカウントに異動したとき毎回Credentialをrevokeするのが大変
- Github Enterpriseを使用しており,アカウント内にあるCIなどのサードパーティ製のサービスがGithubにアクセスする.そのアクセスをIPホワイトリストで制限していて,それぞれのアカウントでTerraformを使って管理したい.
- アカウントは顧客が使っているのでTerraformでのインシデントはなくしたい.Terraformに関するプルリクエストをマージする際に承認ステップのあるスマートなワークフローが欲しい.
Terraform Enterpriseを使う際一緒にやったこと
- モジュールの構造を変更.リソース単位ではなくユースケース単位によって管理
- Workspacesの統合
- 140近くあったWorkspacesを半分にした
- CredentialではなくAssumeRollとExtendIDで管理
- Terraformを0.12へバージョンアップ
- tfstateは現状のものから復元するために800行のShell書いた
はまったポイント
感想
モジュールをユースケース単位で分割するのは良いなと思った.あと,Terraformの現状をインポートしたShellが気になった.
www.slideshare.net
merpay Vault on GKE
マイクロサービスにおける認証方法でどのようにVaultを使っているかを話された.
- Vaultを使い始めた理由
- メルペイユーザが増えてきてCloud KMSのパフォーマンス劣化が気になり始めた時,Kubernetesっぽく扱えるVaultがその代替になりそうだったから
- Vaultはクラスタが組めてHigh Availability構成にできる
- Vaultの管理
- 導入当時はVaultの管理は全て自作だったが,今はHELMを使って管理している.公式にはKubernetesのバグサポートとDatadogの設定ができるくらいなので公式は使っていない.
- よかったこと
- 開発者にはreadのみをSREにはread・write両方をVaultに対して実行できるようにTerraformを作るのがよかった.
感想
Vaultも初めて知った勢なのでまずは使い方を調べてみる.あと,セキュリティに関するところは管理側で握っておき,それ以外は開発側に任せる運用はすごく分かるしやっていこうと思った.
grasysにおけるConsulの位置付けと実用例
grasysでConsulがどのように活用されているかを話された.
Service Discoveryによるオーケストレーション
Checks/Health/KVによる監視
- Lockによるクラスタ内排他制御
- Consul Templateの連携
感想
Consulで使える機能が活用事例を交えて多く紹介されている濃い内容だった!自分の業務でも使えそうなものがいくつかあったので検討してみようと思う.
www.slideshare.net
まとめ
- 創業者のMitchellさんが来たHashiCorp Meetupに参加した
- Consulはマルチクラウド,マルチプラットフォームで動く今にぴったりなプロダクトだった
- LTではConsulの活用事例が数多く紹介された
Redmineからメールが送れない問題を解決
AWS EC2のRedmineからメールを送ろうとしてうまくいかなかったのでその辺をまとめてみた.
先に結論を言っておくとAWSの設定というよりはEC2に立てたRedmineの設定の問題だった.
環境
AWS内のEC2にRedmineとPostfixを立てた.RedmineからPostfixを経由してAmazon Simple Email Service(以降SES)にメールをリレーするよう設定した.構成は以下のようになっている.
問題
一通り設定が終わったところでRedmine上からテストメールをGmailのアドレスに送ってみると以下のようなエラーが出た.
とりあえずエラー内容でググってみたところ,公式に以下のように書いてあった.
メールのリレーサーバーのSSL証明書の確認で問題が発生していると考えられます。取り急ぎの対処として、対応する email_delivery セクションに以下の設定を追加してください。
enable_starttls_auto: false
» メールの設定例 - Redmineガイド
実際に上記のようにRedmine側を設定してメールテストをすると確かに送ることができた. ただ,この時自分はどこの間の経路で証明書にエラーが出て通信を暗号化できていないか分かっていなかったので,PostfixとSES間,SESとGmail間の暗号化がされているか調べてみた.
調査
まずは,SESとGmail間の通信が暗号化されているか確認する.GmailヘルプによるとGmail上から以下の手順で確認できる.
受信メールが暗号化されているか確認する
- メールを開きます.
- メールの受信者リストの右にある下矢印をクリックします.
- 表示される南京錠アイコンの色は,メールの送信時に使用された暗号化のレベルを示します. 送受信時のメールの暗号化 - Gmail ヘルプ
暗号化のレベルに応じてアイコンの色が異なる.それぞれの意味は以下の通り.
暗号化のアイコンの意味
- 緑(S/MIME - 高度な暗号化): 機密情報が含まれているメールに適しています.送信相手の公開鍵がある場合,送信するすべてのメールが S/MIME で暗号化されます.暗号化されたメールは,対応する秘密鍵を持つ受信者のみ復号化できます.
- 灰色(TLS - 標準的な暗号化): ほとんどのメールに適しています.TLS(Transport Layer Security)は S/MIME に対応していない他のメールサービスとやり取りするメールで使用されます.
- 赤(暗号化なし)暗号化されないため,メールの安全性が保証されません.送信するメールが確実に暗号化されないという予測は,過去にこの宛先のドメインに送信されたメールに照らし合わせて行われます. 送受信時のメールの暗号化 - Gmail ヘルプ
Gmail上で確認してみると灰色だったのでTLSで暗号化されてそう.
次に,PostfixとSES間の通信が暗号化されているか確認する.確認方法はPostfix側の送信ログを見てTLSのハンドシェイクがされてそうかどうかで確認する.送信ログにTLS通信のハンドシェイクはデフォルトのログレベルだと出力されないのでPostfixの設定を変える.
sudo postconf -e 'smtp_tls_loglevel = 2' sudo postfix reload
Redmineからメールを送ってみると以下のようなログが確認された.TLS通信のハンドシェイクがなされていそう.
ip-hoge postfix/smtp[26090]: SSL_connect:SSLv3 read server certificate A ip-hoge postfix/smtp[26090]: SSL_connect:SSLv3 read server key exchange A ip-hoge postfix/smtp[26090]: SSL_connect:SSLv3 read server done A ip-hoge postfix/smtp[26090]: SSL_connect:SSLv3 write client key exchange A ip-hoge postfix/smtp[26090]: SSL_connect:SSLv3 write change cipher spec A ip-hoge postfix/smtp[26090]: SSL_connect:SSLv3 write finished A ip-hoge postfix/smtp[26090]: SSL_connect:SSLv3 flush data ip-hoge postfix/smtp[26090]: SSL_connect:SSLv3 read finished A
ここまでの確認でEC2より外へは暗号化がされていることが分かったので安心したのだが,結局Redmineはどこの通信で証明書エラーが出て暗号化できなかったのか最初は分からなかった.しばらく考えた結果,RedmineとPostfix間の通信で暗号化されていないことにやっと気が付いた.なぜかPostfixに関してはSESに送信するSMTPの意識だけしていてRedmineから通信を受けるサーバとしてのSMTPを意識していなかった.SMTPサーバでは証明書等の設定をしていなかったためこのエラーが出たというわけである.というわけで,EC2内でのメールのやりとりに暗号化は不要なのでこの設定でよしとなった.
まとめ
Configで検知した異常をSNSとLambdaを使ってSlackへ通知してみた
AWSでサービスを動かしているとSlackと連携して通知をする機会がしばしばあると思う.社内で,AWSのConfigで検知した異常をSlackに通知してほしいと言われたので,Simple Notification Service(以降SNS)とLambdaを使って実現した.今回はその方法を書いていく.
はじめに
弊社は自社サービスが多く,アカウントはサービス単位で発行され,開発エンジニアはそれぞれのアカウントで環境を構築している.今回は,各アカウントで設定されたConfigからSNSとLambdaを経由して会社共有のSlackに通知する.SNSとLambdaは各アカウントごとに作成するのはコストの面でよくないので,インフラチームのアカウントで1つだけ作成する方針にしている.ということで今回は以下のような設計で構築した.
なお,Slackへ通知する際に必要なIncoming Webhookの設定はこの記事では割愛する.公式を参考にしていただくとスムーズに設定できるかと思う.
手順
Configを作成
Configとは,AWSリソースの設定を評価,監査,審査できるサービスである.Configではリソースを評価するためのルールを設定する.今回設定するルールは,インバウンドのsshを設定しているセキュリティグループでIPをフルオープンにしていないかチェックするrestricted-ssh
にする.ルールは自由に選んでよいが,通知テストをする上では一時的にルールを破る必要があるのでそれに適したルールを設定するのがよいと思う.また,設定項目にAmazon SNS トピック
があるが,SNSトピックの設定をした後でないとarnの入力ができないため一旦このままにしておく.その他はデフォルトのまま.
SNSを作成
SNSとは簡単に言うと「何らかの通知を送信したい人(またはシステム)から、受信したい人(またはシステム)へ通知を送る仕組み」を提供するマネージドサービスである.SNSでは「送信したい人」を発行者と呼び,「受信したい人」を購読者と呼ぶ.そして,双方を繋げる中間役をトピックという.SNSを利用する際はまずトピックを作成し,そのトピックと通信できる発行者・購読者を設定することで,アクセスを制御することができる.今回の場合,発行者は各サービスのConfigで,購読者はLambdaとなるように設定する.トピック作成時に出てくるアクセスポリシーの設定では異なるアカウントからの発行を許可するよう設定しておく.
Configに通知先としてSNSを設定
トピックの設定が終わるとarnが発行されるので,それをConfigに設定する.ConfigとSNSは別アカウントにあるため別のアカウントからトピックを選択
を選び,トピックのarnを入力.
Config用のロールを作成
Configにアタッチされているポリシーにもトピックのarnを設定しなければならない.Configを作成する際ロールを新規で作成すると,AWSServiceRoleForConfig
というロールが割り当てられる.そのロールにはSNSへの発行(Publish)を許可するポリシーが設定されていないので,SNSに発行(Publish)可能なロールを新たに作成してConfigにアタッチする必要がある.まずはロールを作成.
次に,以下のようなポリシーを作成し上記のロールにアタッチ.
{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": "sns:Publish", "Resource": "arn:aws:sns:hogehoge" } ] }
このロールをConfigから選択する. これでConfigからSNSまでの通知の設定は完了.
Lambdaを作成
SNSから通知を受け取り,Slackへ通知するためのLambdaを作成する.Python3.7で以下のように記述した.
import json import os import urllib.request SLACK_WEBHOOK_URL = os.environ['SLACK_WEBHOOK_URL'] def lambda_handler(event, context): # cloudwatchにログを吐くため用のデバッグ文 print(event['Records'][0]['Sns']['Message']) message = json.loads(event['Records'][0]['Sns']['Message']) title = message['configRuleName'] detail = message['awsAccountId'] + 'アカウントで' + message['configRuleName'] + 'の異常が検知されました' post_slack(title, detail) def post_slack(title: str, detail: str) -> None: payload = { 'attachments': [ { 'color': '#D50200', 'pretext': title, 'text': detail } ] } request = urllib.request.Request( SLACK_WEBHOOK_URL, data=json.dumps(payload).encode('utf-8'), method="POST" ) try: with urllib.request.urlopen(request) as response: print(response.read()) except urllib.error.HTTPError as err: print(err.code)
やっていることは単純で,ConfigからSNSを経由して受け取った情報から,Slackで表示する文字列を生成してSlackへ投稿するだけである.SLACK_WEBHOOK_URL
の部分はIncoming Webhookの設定で吐き出されるチャンネルのWebhook先のURLである.冒頭でも言及した通り,SlackのIncoming Webhookの設定方法はここでは割愛する.さらに,SNSからの通知をトリガーにLambdaを動作させたいのでトリガーに先ほど作成したSNSを設定する.
SNSの購読者にLambdaを設定
Lambdaを作成した際にarnが発行されるので,それを使いSNSにLambdaを購読者として設定する.Lambdaでトリガーを設定するとここは自動で設定されているかもしれない.これでSNSに発行されたConfigの情報をLambdaで受け取ることができる.
テスト
ここまでで通知の設定は完了した.試しにConfigが設定してあるセキュリティグループのインバウンドを任意の場所からsshできるよう設定してみると,ちょっと経ってからSlackに通知が届く.正直どのタイミングでConfigがSNSに通知するのかよく分かっていない. また以下のようにコンソールから,ConfigとSNS間,SNSとLambda間,LambdaとSlack間で結合テストができる.
はまったところ
SNSへ発行可能なConfig用のロールを作成しなければならないことに気づかずはまってしまった.ConfigからSNSへの通知テストは通ったので,ConfigとSNS間はあまり疑っていなかった.しかし,それはコンソールにログインしているユーザのロールにSNSへの発行が許可されていて,コンソール上からは通知テストがうまくいっているというだけだった.ここで学んだことは,AWSだとどのサービスが動いていて,どのロールが適用されているかを理解し,アクセス先はもとよりアクセス元のACLもしっかり考慮しないといけないこと.
感想
ドットインストールでVimに再入門してみた
少し前に今使っているIDEのエディタをVimに変更したが,Vimの機能を使いこなせていない感が否めなかったので改めてドットインストールで再入門することにした.今回は自分が知らない・使っていないコマンドについてまとめてみる.
https://dotinstall.com/lessons/basic_vim
Vim入門(全18回)
- 01 Vimを使ってみよう
- 02 Vimのモードについて
- 03 ファイルの保存,読み込みについて
- 04 移動をマスターしよう(1)
- 05 移動をマスターしよう(2)
- 06 ビジュアルモードについて
- 07 カット,コピー,貼付けについて
- 08 検索をしてみよう
- 09 置換をしてみよう
- 10 操作の取り消しをしてみよう
- 11 ウィンドウの分割をしよう
- 12 タブを使ってみよう
- 13 直前の操作を繰り返す
- 14 インデントを揃えよう
- 15 補完機能を使ってみよう
- 16 矩形選択後に編集する
- 17 テキストオブジェクトを扱う
- 18 便利な設定を使う
03 ファイルの保存,読み込みについて
05 移動をマスターしよう (2)
- ノーマルモードになり,
f + 任意の文字
でその行に指定した文字があればそこに移動する.;
で順方向に再検索,,
で逆方向に再検索できる. - ノーマルモードになり,括弧にカーソルを合わせて
%
を押すとその括弧に対応するもう片方の括弧へ移動する.始めの括弧,閉じ括弧どちらでも使うことができる.
08 検索をしてみよう
- ノーマルモードになり,ある単語にカーソルを合わせ
*
を入力するとその単語について順方向に検索してくれる.#
を入力すると逆方向に検索する.
09 置換をしてみよう
:s/置換前文字列/置換後文字列
でカーソル行を対象にヒットした置換前文字列を置換後文字列に変換する.ただし,置換されるのは最初にヒットした文字列のみ.:s/置換前文字列/置換後文字列/g
でカーソル行全体を対象に置換する.%s/置換前文字列/置換後文字列/g
でファイル全体を対象に置換する.%
がファイル全体を表している.%s/置換前文字列/置換後文字列/gc
のようにconfirmを意味するcをつけることでインタラクティブに置換する.
11 ウィンドウの分割をしよう
:sp
で上下にウィンドウが分割され,:vs
で左右にウィンドウが分割される.- ウィンドウ間を移動するときはノーマルモードで
Ctrl+w
を二回押せばよい.複数画面を開いている場合は連打で移動できる. - ウィンドウを閉じる時は
:close
を入力する.
12 タブを使ってみよう
- タブのように新規で開きたい場合は
:tabnew
と入力する.開きたいファイルが決まっている場合は:tabe ファイル名
と入力することで指定したファイルが新規タブで開く. - タブ間の移動はノーマルモードで
gt
. - タブを閉じる時は
:tabclose
. - Vimを立ち上げる時にtabで開きたいときはコンソールから
vim -p ファイル1 ファイル2
. - すべてのタブを対象に置換をしたいときは
tabdo %s/置換前文字列/置換後文字列/g
.
13 直前の操作を繰り返す
- ノーマルモードで
.
を押すと直前の操作を繰り返す.例えば3dd
で3行消したあと他の行で.
を押すとその行以降を対象に3行が削除される.
14 インデントを揃えよう
- ノーマルモードで
=
を押すとインデントを揃えてくれる.
15 補完機能を使ってみよう
- 入力モードで変数名や関数名を入力している途中で
Ctrl + n
を押すと候補が表示される.
17 テキストオブジェクトを扱う
<title>タイトル</title>
- 上記のテキストにカーソルを合わせノーマルモードで
cit
と打つとタイトル
の文字が消え,その位置で挿入モードになる. cit
のc
はアクションを表す.c
の場合は削除して挿入モードに変更.d
は削除,y
はコピーなど他のアクションに置き換える事も可能.cit
のi
は範囲を表す.i
はタグの中身が範囲でa
に置き換えるとタグ全体が範囲になる.上記の場合でa
にするとごと消えて挿入モードになる. cit
のt
はターゲットを表す.t
の場合はタグに対して行う.他にも"
や)
,]
などがある.
18 便利な設定を使う
:syntax on
でシンタックスハイライトが実現できる.:syntax off
で元に戻す.:set tabstop=4
でインデントタブの長さを変えることができる.:set ignorecase
で大文字小文字を無視した検索ができる.:set noignorecase
で元に戻す.
まとめ
Terraform初心者が「Terraform meetup tokyo#2」に参加した
インフラ構成管理ツールの1つであるTerraformの勉強会に参加してきた. Terraformは昨今のクラウド環境でよく使用されていて,AWSやGCP,Azureなど幅広いインフラに対応している. 自分はTerraformを今から取り入れようかなという感じで,それにあたり何か知見を得れればと思い参加した.
個々のアプリのリポジトリでTerraformを管理している話
表題の通りTerraformの管理をアプリケーションごとに書いているという話.
- 良かったこと
- アプリが使用するインフラリソースがわかりやすい
- Terraform変更の影響範囲が明確
- Terraformのアップグレードを必要に応じてできる
- Planが早い
- アプリの変更とインフラの変更を一緒にレビューできる
- 良くないこと
- 同じような修正が何度も必要
- 書き方にムラが出やすい
- CI/CDが大変
- インフラ構成全体の把握に時間がかかる
感想
プロジェクトが少なかったりチームが小さいと小回りがきくのでやりやすそう.またタグでリソース管理元リポジトリがわかるようにしているのは便利そう!
APIがある外部サービスはTerraformで管理できますよ
Providerのない外部サービスでもそのサービスがAPIさえ提供していてくれればCustom Providerを作って構成管理できるという話.TwilioのProviderを作成された際の知見を話された.
- クラウド以外の外部サービスを使う場合でも有名なサービスであればTerraformにProviderが用意されている
- APIを提供している外部サービスはTerraformのProviderを自作すればTerraformで管理できる
- Providerの作り方
- 公式ドキュメントをやる
- TerraformProvider実践を読む
- 既存のProviderコードを読む
感想
Terraform側が提供しているProviderもまぁまぁあるが,APIさえあれば管理できちゃうともなるとWebで使っているサービスに関してはほとんど管理できるのではと感じた.
Terraformerのおはなし
Terraformerのアーキテクチャと機能追加のプルリクエストを送った際の知見を話された.
- Terraformerとは,対応しているSaaS,IaaSの既存情報を元にtfstateとtfファイルを作成してくれる
- Terraformのアーキテクチャ
- 前処理
- Providerとの通信
- 取得結果のparse
- 機能追加で実際コードを書くのはアーキテクチャでいう前処理部分だけ,簡単!
- TerrafomerもすごいけどTerraformのplugin機構もすごい
感想
機能追加のプルリクエストなのにコード書いてる部分少なくてお手軽に実装できそうだなと思った. Terraformすら触っていない自分としては,既存のAWS環境をTerraformerでimportしてみてどのようなstateが出力されるのか,1から作成するよりも作業が少なくなるのか試してみようと思う.
FOLIOのTerraform運用tips
FOLIOさんでTerraformを運用しているやり方が全体的に見えるようなお話をされた.
- Terraformコマンドの運用
- ディレクトリ構成
- 変数の格納
- アカウントを超えて全体で使う変数とアカウント固有の変数で分けている
- Terraformの書き方
- 属人化を防ぐことやTerraformの破壊的変更への対策等の理由からコメントは重要視していた.特にresourceに対するコメントは必須らしい
- 全体設計レビュー
感想
Terraformで迷いそうなディレクトリの構成や開発の仕方など全体に渡って実用例を解説していただけてとても参考になった. 運用の話においては,誰が見てもわかるようにコメントを残すことを徹底されているところに共感した.
World Cafe
ここからはWorld Cafeというディスカッションを各テーブルで行う時間. 簡単に言うとWorld Cafeとは,あるトークテーマについてみんなで話し合う場である.詳しくは以下の資料を参考にしていただければと思う.
自分は初めてのWorld Cafeだったが,控えめに言ってとてもすばらしいイベントだった. 勉強会に集まったみんなと情報共有することで新たな知見を得ることができるし,悩み相談もできる. World Cafeでは,その場にいる参加者同士でコミュニケーションを取ることの良さを改めて感じた. 勉強会によりけりかもしれないが,どの勉強会もWorld Cafeを取り入れてくれると嬉しい.
Terraform WorkSpace機能を活用してきたノウハウを一挙公開
Terraform WorkSpace機能の紹介.Terraform WorkSpace機能はThe Twelve-Factor App (日本語訳)を考える上でも役に立つとお話しされていた.
- The Twelve-Factor Appの1つである
開発/本番環境の一致
をTerraform WorkSpaceで実現できる- resource_countを使って不要な環境では立ち上げない
- インフラ用dev環境がWorkspaceで作れる
- アプリケーションの構成をインフラでも再現したい時,Workspaceを作成してTerraformで記述されたリソースがどのように立ち上がっていくのか確認できる
- Workspaceを使ってて辛かったこと
- 使っている人が少ないので情報量が少ない
- Workspaceやめましたみたいなブログがあって悲しくなる
感想
自分が初心者なのでTerraform WorkSpaceについての情報量が少ないのは心もとないがメリットはありそうなので検討してみたい.
www.slideshare.net
TerraformとAzure Pipelinesを用いたプロビジョニングの自動化
TerraformとAzureの組み合わせで実現できたことできなかったこと,こけそうなポイント,今後の課題などをお話しされた.
- 実現できなかったこと
- Event Hubsのイベントサブスクリプションの構成
- 技術的に可能そうだが,実現できなかった
- Key Valutのアクセスポリシー
- ポータルから手動で構成したほうが運用しやすい
- Event Hubsのイベントサブスクリプションの構成
- こけそうなポイント
- App ServiceにApplication Insightsを構成する際,APPINSIGHTS_INSTRUMENTATIONKEYを記載しただけでは有効化されない
- SQL ServerのセキュリティはTerraformで構成不可
- Traffic Managerのステータスコードの範囲はTerraformで構成不可
- 今後の課題
- Azure Pipelinesのymlファイルを含めたときのフォルダ構成のベストプラクティス
感想
Azureは普段から触っていないが,社内のサービスで利用しているところはあるのでそのサービスでTerraformを使うことがあれば参考になりそう.
Terraform-provider-awsのコントリビュータになろう!
Terraform-provider-awsコントリビュータになるまでをお話しをされた.
- コントリビュートへの道
- コードを書かないコントリビュートもある
- 一番大変なのは「課題を見つけること」
- とりあえずやってみよう
- コードを書かないコントリビュートもある
- ドキュメントの修正
- typo
- ドキュメントが追従してない etc…
- 不具合の報告
- ドキュメントの修正
一番大変なのは「課題を見つけること」
- GitHubのIssueを眺める
- 「Refactor」「technical-debt」などで検索
- GitHubのIssueを眺める
とりあえずやってみよう
感想
Terraform Providerに限らず他のOSSでも使えそうで参考になる.コードほぼかかなくていいのはお手軽!
まとめ
Terraformを今後使っていこうとしている身としては参考になる情報満載でとても有意義な時間だった! 特に,World Cafeでたくさん運用Tipsを聞くことができて,また参加しようという気持ちになった! 次の機会までに,自分も使ってみたtipsや感想を共有できるようになっていたいと思う.