nabeo がピーしているブログ (仮)

どーも、nabeop です

cdktf 再入門

どうも、型にハマらない人生を歩みたいけど、コードを書く時は型が欲しい id:nabeop です。

1年くらい前に cdktf に入門したあとは changelog は追っていたけど、使う機会がなかった。 ちょうど AWS アカウント単位で検証環境を複数作ることになったので、cdktf に再入門してみた。

最初に触ったときは v0.0.18 で現時点では v0.9.0 だった。

続きを読む

AWS Certified Security - Specialty に合格しました

会社の資格取得補助を利用して、AWS Certified Security - Specialty の資格を取得できた。

一昨年は AWS Certified Solutions Architect – Associate に合格したけど、去年は AWS Certified Advanced Networking - Specialty に落ちちゃったので、今年こそは絶対に取るぞと気合を入れていたのでなんとか取得できて嬉しい。

AWS Certified Security - Specialty は AWS が認定している資格の1つで公式の説明では以下のようになっています。

この資格は、組織がクラウドイニシアチブを実装するための重要なスキルを持つ人材を特定して育成するのに役立ちます。AWS Certified Security – Specialty を取得することで、AWS クラウドにおけるデータやワークロードのセキュリティ確保に関する専門知識が認定されます。 https://aws.amazon.com/jp/certification/certified-security-specialty/?ch=sec&sec=rmg&d=1

詳しくは公式の説明を読んでもらうとわかると思うけど、要するに AWS のサービスのうちセキュリティ分野に特化した専門知識を持っているかを試される、という感じです。最近は AWS アカウント周りの整備をやっていてセキュリティ周りもスコープに入っていたので仕事でやっていることの再確認も兼ねてちょうど良い感じだった。

AWS Certified Security - Specialty の取得を考えている人の参考になるかもしれないので、資格取得のためにやった準備とかをまとめておこうと思う。

会社で資格取得補助をやっているという関係で毎年この時期に資格取得のための勉強会が立ち上がるので、その流れにのって週一回に1時間ほど同じに用に資格取得を目指す同僚とオンラインで黙々と勉強をしていました。このエントリも勉強会の時間に書いています。

すでに AWS については3年程の実務経験があって、直近では AWS アカウントのセキュリティやガバナンス強化の設計をしていたので、ある程度の専門知識はありそう(むしろ無いと困る)という感じだったので、初手で模試を受けてみました。Solutions Architect の Associate に合格していたので、クーポンが使えるのでお得だったんだけど、僕がうけた模試は結果がわかるけど、具体的にどの問題が不正解だったのかがわからないタイプだった。一緒に勉強会に参加していた id:wtatsuru さんは AWS Skill Builder の模試を受けていて、こっちは解答と解説がでていたそうなので、失敗したなーと思っています。

wtatsuru.hatenadiary.com

最初に受けた模試の結果では総合スコアが 75% で合格ラインには達していそうだったけど、スコアが低い分野があったので、スコアが低かった分野を中心に勉強をするという方針を立てた。

勉強の教材は AWS Certified Security - Specialty に特化した参考書が会社に転がっていたので、一通り目を通してみて、スコアが低かった分野は Blackbelt で知識を保管するという作戦です。

会社に転がっていた参考書はこれ

試験はリモートでの試験も選択可能だったけど、会社の近くに試験会場があったし、リモート受験して苦労している同僚もみていたので、試験会場で直接受けた。試験の内容は模試と同じような雰囲気だったのでどこかの時点で模試は受けておいた方が良いと思う。あと、AWS におけるセキュリティといえば IAM や KMS 、GuardDuty や Security Hub とかが思い浮かぶけど、試験ではそのようなセキュリティサービスに加えて、CloudFront などのサービスでセキュリティを担保するため構成が問われるような問題も出ていた。

来年も勉強会は開催されると思うので、次回は DevOps Engineer Professional か Solutions Architect - Professional あたりに挑戦するかと思っている。

OpenSSH で複数の公開鍵を使い分ける

人間、生きていると複数の公開鍵を優先順位をつけて使い分けたくなる時があります。例えば、OpenSSH 8.8/8.8p1 で ssh-rsa 鍵による署名が無効になるので、この機会に ssh-rsa 鍵を捨てたいけど、本当に全部のサーバを置き換えたか自信がないので、古い鍵にフォールバックできるようにしておきたい、などです。

ssh_config (5) では以下のように IdentityFile を複数定義することができると書いてあります。

 IdentityFile
         Specifies a file from which the user's DSA, ECDSA, Ed25519 or RSA authentication identity is read.  The default is
         ~/.ssh/id_dsa, ~/.ssh/id_ecdsa, ~/.ssh/id_ed25519 and ~/.ssh/id_rsa.  Additionally, any identities represented by the
         authentication agent will be used for authentication unless IdentitiesOnly is set.  If no certificates have been explic-
         itly specified by CertificateFile, ssh(1) will try to load certificate information from the filename obtained by appending
         -cert.pub to the path of a specified IdentityFile.

         Arguments to IdentityFile may use the tilde syntax to refer to a user's home directory or the tokens described in the
         TOKENS section.

         It is possible to have multiple identity files specified in configuration files; all these identities will be tried in
         sequence.  Multiple IdentityFile directives will add to the list of identities tried (this behaviour differs from that of
         other configuration directives).

         IdentityFile may be used in conjunction with IdentitiesOnly to select which identities in an agent are offered during
         authentication.  IdentityFile may also be used in conjunction with CertificateFile in order to provide any certificate
         also needed for authentication with the identity.

「all these identities will be tried in sequence.」なので、~/.ssh/config で以下のように書いたら ~/.ssh/id_ed25519~/.ssh/id_rsa/ の順番で鍵を使ってくれそうです。

IdentityFile ~/.ssh/id_ed25519
IdentityFile ~/.ssh/id_rsa

これは真でもあり偽でもあります。

具体的には ssh-agent に ~/.ssh/id_rsa が登録されている状態で、設定ファイルを上記のように書き換えた場合、既に ssh-agent に登録されていた ~/.ssh/id_rsa が使用する鍵ペアの公開鍵として使われ、 次に ~/.ssh/id_ed25519 の鍵ペアが使われていました。

このため、ssh-add -D して ssh-agent に記憶喪失になってもらうか、ssh-agent をリスタートさせる必要がありました。

ssh-ed25519 公開鍵を受け付けない ssh サーバを準備して意図した優先順位で鍵ペアが使われているかを確認したら、ssh -v の出力から意図通りに ssh-rsa にフォールバックしてくれることを確認しました。

フォールバックに成功した例:

# id_ed25519 -> id_rsa の順番で使いたいと表明している
debug1: Will attempt key: /Users/nabeop/.ssh/id_ed25519 ED25519 SHA256:PMVZkeWRos6nqGxKtIJXfAlJK6H2z1GOjxnWPTm9/T8 explicit agent
debug1: Will attempt key: /Users/nabeop/.ssh/id_rsa RSA SHA256:wMZ0uFG/ig9QLVRaamjzL6JKCDmB6SuqM4V5lpaqkqU explicit agent
# id_rsa にフォールバックした
debug1: Authentications that can continue: publickey
debug1: Next authentication method: publickey
debug1: Offering public key: /Users/nabeop/.ssh/id_ed25519 ED25519 SHA256:PMVZkeWRos6nqGxKtIJXfAlJK6H2z1GOjxnWPTm9/T8 explicit agent
debug1: Authentications that can continue: publickey
debug1: Offering public key: /Users/nabeop/.ssh/id_rsa RSA SHA256:wMZ0uFG/ig9QLVRaamjzL6JKCDmB6SuqM4V5lpaqkqU explicit agent
debug1: Server accepts key: /Users/nabeop/.ssh/id_rsa RSA SHA256:wMZ0uFG/ig9QLVRaamjzL6JKCDmB6SuqM4V5lpaqkqU explicit agent
Authenticated to 127.0.0.1 using "publickey".

ssh-ed25519 が使えた例:

# id_ed25519 -> id_rsa の順番で使いたいと表明している
debug1: Will attempt key: /Users/nabeop/.ssh/id_ed25519 ED25519 SHA256:PMVZkeWRos6nqGxKtIJXfAlJK6H2z1GOjxnWPTm9/T8 explicit agent
debug1: Will attempt key: /Users/nabeop/.ssh/id_rsa RSA SHA256:wMZ0uFG/ig9QLVRaamjzL6JKCDmB6SuqM4V5lpaqkqU explicit
# id_ed25519 が使われた
debug1: Authentications that can continue: publickey
debug1: Next authentication method: publickey
debug1: Offering public key: /Users/nabeop/.ssh/id_ed25519 ED25519 SHA256:PMVZkeWRos6nqGxKtIJXfAlJK6H2z1GOjxnWPTm9/T8 explicit agent
debug1: Server accepts key: /Users/nabeop/.ssh/id_ed25519 ED25519 SHA256:PMVZkeWRos6nqGxKtIJXfAlJK6H2z1GOjxnWPTm9/T8 explicit agent
Authenticated to 127.0.0.1 using "publickey".

TLS で暗号化された内容を見たいとき

稀に TLS で暗号化されたパケットの中身を確認したくなる時があるけど、Change Cipher Spec のあとは暗号化されていて困る。TLS はそういうんもんなので普段は困らないけど、handshake の様子とかをつぶらに確認したくなる時とかに途方に暮れたりする。

こういう時は handshake 中の pre master secret などと呼ばれる暗号化に使っている鍵をどうにかして知る必要がある。

で、だいたいのプログラムには通信に使用した秘密を保存することができる。ググったり、help を眺めると書いてあるけど、よく忘れるのでメモっておく。

curl の場合は環境変数に pre master secret の保存先を以下のように指定する。

SSLKEYLOGFILE=./pre-master-secret.log curl -I https://nabeop.hatenablog.com/

openssls_client の場合はオプションに pre master secret の保存先を以下のように指定する。

openssl s_client -servername nabeop.hatenablog.com -connect nabeop.hatenablog.com:443 -keylogfile=pre-master-secret.log < /dev/null

あとは wireshark なり tshark でゲットした pre master secret をキャプチャしたデータにくわせると、複合された状態でデータを眺めることができる。

1ヶ月ほど開発版の emacs で生活してみた

macOSemacs を使うには日本語入力周りでパッチを当てる必要があったので、長らく emacs は安定版を使っていた。そんなある日、現実逃避でググっていたら emacs 28.0.50 で macOS でも WebKit を使えるようになったと知った。

Linux では xwidget が使えるようになっていて、lsp-ui-doc でいい感じに Doc コメントが表示されるんだろーなーと、眺めていたのだった。

開発版の emacs のビルドが 10分くらいで終わって感動したのちに、lsp-ui の設定を以下のようにしてみた。

(use-package lsp-ui
  ;; [snip]
  :custom
  (lsp-ui-doc-use-childframe (featurep 'xwidget-internal))
  (lsp-ui-doc-use-webkit (featurep 'xwidget-internal))
  ;; [snip]
  )

(featurep 'xwidget-internal) しているのは環境によっては emacs 27 を使っているので、イイ感じに吸収しようとした結果です。あとは開発版から安定版にいつでも戻れるようにしておきたかったからw

CDK を TypeScript で書いているときにドキュメントが childframe で表示されてかなりイイ感じでコードがかける。xwidget-webkit-browse-url とかして URL を読み込むとキーバインドが xwidget に完全に取られて、Ctrl-gkeyboard-quit もできない状態になるけど、lsp-ui-doc 以外で使う気になっていないのであんまり困っていない。

wl で plain text と html なマルチパートメールを読む時に WebKit で html パートのほうを表示されると困るなーと思っていたけど、今のところそういうことにはなっていない。

emacs 28.0.50 にしてから3回ほど HEAD を移動させてビルドしているけど、他でも困ったことはないから、ひとまずこのまま普通に生活できそうだなー。

gh コマンドで複数のサイトを使い分けられるようになっていた

gh コマンドとは github の公式 cli ツールです。

github.com

ある日、ボーッと gh コマンドの補完候補を眺めていたら、gh auth login というコマンドが生えていたことに気づきました。ドキュメントを読んでみると、複数のサイトの認証情報を持てるぽい。

cli.github.com

僕が使っている githubgithub.com と Github Enterprise の2種類があって、普段はこの2つのサイトを行ったり来たりしていたので、複数のサイトの認証情報を使い分けられるのは願ったり叶ったりでした。

使い方は gh auth login で各サイトの認証情報を保存すると、GH_HOSTGH_REPO という環境変数か、カレントディレクトリのレポジトリに応じて認証情報を使い分けてくれるぽい。

たとえば、自分に割り当たっている PR の状況をみるときは GH_REPO をいい感じに変えて gh pr status を実行する、といった感じです。このおかげで1年くらいマージ待ちになっていた PR を発見できました。

cdktf に入門した話

本記事ははてなエンジニア Advent Calendar 2020 の2日目の記事です。昨日は id:miki_bene さんのページのコンテンツから離れたタイミングのブラウザイベントの選び方 - ドキュメントを見たほうが早いでした

qiita.com

現職になってからクラウドプロバイダーは AWS が中心だったので、TypeScript で AWS CDK をつかっていました。最近になって Google Cloud にも興味が出てきたので、Terraform も選択肢として入ってくるようになりました。ただ、TypeScript でインフラを構成することになれていると HCL では表現力が足りないなーという課題感も感じていました。

そんなときに CDK の Terraform 版である cdktf の存在を知ったので、Terraform に入門するついでにお試しで cdktf にも入門してみました。

cdktf はこのエントリの執筆時点で v0.0.18 でまだまだ開発版という位置付けで正式版になったらいろいろと変わると思います。以下は v0.0.18 での知見です。

cdktf の始め方

HashiCorp のドキュメントに始め方があります。

learn.hashicorp.com

CDK と同じように TypeScript 向けのプロジェクトは以下のように初期化してテンプレートが生成されます。

cdktf init --template=typescript --local

cdktf init した直後のディレクトリは CDK と同じような感じです。

$ ls -a
./                 .gitignore         main.d.ts          node_modules/      tsconfig.json
../                cdktf.json         main.js            package-lock.json
.gen/              help               main.ts            package.json
$

唯一、 .gen というディレクトリだけが見慣れない感じだったので中身を確認したところ、初期状態では cdktf.jsonterraformProvidersaws が指定されている関係で Terraform の AWS プロバイダ向けと思われる ts が .gen/providers/aws 以下に配置されていました。

あと、help というファイルに cdktf での開発に必要なコマンドが書かれていて便利でした。

Google Cloud 向けに環境を整える

初期状態では AWS を想定されていますが、今回は Google Cloud を対象としたいので Terraform プロバイダを変更する必要があります。Terraform プロバイダ設定は cdktf.json で以下のように書き換えます。

{
  "language": "typescript",
  "app": "npm run --silent compile && node main.js",
  "terraformProviders": [
    "google@~> 3.0"
  ]
}

このままでは .gen 以下には AWS 向けのプロバイダが入っているので help にかいてあるとおり Google Cloud のプロバイダを導入します。

npm i -a @cdktf/provider-google
npm run get

cdktf のある生活

Google Cloud 向けのクレデンシャル情報を用意したりと Terraform / Google Cloud としてのお作法はありますが、だいたい AWS CDK と同じように開発ができます。

つまり、

  • ts ファイルで記述して
  • npm run compile して、ts ファイルから js ファイルと d.ts ファイルを生成して、
  • npm run diff で差分を確認して、
  • npm run deploy して適用する

という感じです。

npm run diffterraform plannpm run deployterraform apply に相当しています。

また、package.json の内容などを特に変更しなければ cdktf.out が Terraform としての working directory という扱いになっていそうです。

$ ls -a cdktf.out
./           ../          .terraform/  cdk.tf.json  plan
$

たとえば、cdktf.out/planterraform plan -out plan したときに生成されるファイルと同じ感じでした。つまり、cdktf.out ディレクトリに移動したら terrafom show plan で plan 時の情報を確認できたりします。cdktf.out/plan を使って差分を確認する様子は別エントリで書いています。

nabeop.hatenablog.com

Terraform プロバイダーとの対応関係

.gen/providers/google の中にプロバイダーのリソースやデータソースに対応するクラスが定義されています。

また、各クラスの実装はプロバイダーのスキーマから生成されており、以下のような対応関係になっているみたいです。

  • リソース
    • リソース名についているプロバイダーの文字列を削除して、アッパーキャメルケースに変換
  • データソース
    • データソース名に Data プレフィックスをつけて、アッパーキャメルケースに変換

つまり、

というような感じです。

snapshot テストしたい

せっかく TypeScript で IaC をしているので、テストも書いておきたいところです。AWS CDK を使っている時は snapshot テストだけは整えるようにして、バージョンアップによる不意の変更がわかるようにしています。cdktf でも同じようにしたいので調べてみたところ、cdktf のなかに Testing クラスが定義されていました

試しに jest 周りを整えて、main.test.ts を書いてみたら snapshot テストができました。

import { SandboxStack } from './main';
import { Testing } from 'cdktf';

describe ("sandbox-project", () => {
  test("snaphost test", () => {
    const app = Testing.app();
    const stack = new SandboxStack(app, 'test-stack', {
      credentials: '{}',
    });
    const results = Testing.synth(stack);
    expect(results).toMatchSnapshot();
  });
});

cdktf を触ってみた感想

まだまだ開発版なので足りていない機能はあるという前提ですが、以下のような感想です。

  • TypeScript の資産が活かせるので開発はすんなり始められそう
    • Terraform プロバイダーから半ば機械的に生成された ts ファイルをベースにしているので、HCL を書いている感はある
  • AWS CDK に慣れた身では cdktf diff の出力内容だけだと、どのような変更が行われるかわからず不安になる
    • 変更があるリソースはわかるけど、変更内容まではわからないというところが厳しかった

cdktf のレポジトリをみると活発に開発されていて、プロジェクトのロードマップもあるので正式版のリリースを気長に待とうかという気持ちです。

明日は id:dekokun さんです。