あんパン

こしあん派

CDKでEC2を建立するときになんかする

めっちゃ小ネタだし知ってるわって人も多そうな話題なのだけど、CDKでEC2建立するときに addUserData でなんかするのが便利。

例えば、Perlの最新版をインストールしたいときは以下みたいな感じでxbuildを使って達成できる。

const bastion = new ec2.BastionHostLinux(this, 'bastion', { vpc });
bastion.instance.addUserData(
  'yum -y update',
  'yum -y install gcc',
  'wget https://github.com/tagomoris/xbuild/archive/refs/heads/master.zip -P /tmp',
  'unzip /tmp/master.zip -d /tmp',
  '/tmp/xbuild-master/perl-install 5.36.0 /opt/perl-5.36',
);

CDK実行時は addUserData 内のコマンドを待つわけではないので、建立直後は実行完了までしばらく待つ必要がある。

ちなみに BastionHostLinux を使う必要はない。 Instance でOK。SSM agentが入っているとPrivate Subnetに建てたとしてもWebコンソールからシュッと接続できるため自分は便利に使っている。が、(いまのところ)Amazon Linux 2が建つので要注意という感じではある。

ちょっと凝ったことしたいなら、curlで取得して実行する手もある。けどあんまセキュアな行いではないと思う…

const bastion = new ec2.BastionHostLinux(this, 'bastion', { vpc });
bastion.instance.addUserData(
  'sh -c "$(curl -fsSL ...)"',
);

自分の場合はときどきRTMPのプロキシを用意したくて、nginx-rtmp-module入りのNginxをビルドするのに同じようなことをしている。

以上、わざわざプロビジョニングのあれこれを考えたくなくて環境が整ったEC2をシュッと建てたいときに使えるテクでした。

はてなブログで見出しへのリンクを表示する

つい最近、はてなブログの見出し(h1からh6までのタグ)にid属性が付与されるようになった。

staff.hatenablog.com

ということは、見出しへのリンクを作って共有できる。ただ普通に暮らしていると、このリンクを生成するためにDeveloper Toolsを表示して見出しのidを入手してURLにhash fragmentを設定して… という手順になってしまいやや煩雑。GitHubのMarkdownのように、hoverしたらリンクアイコンが表示されて見出しのリンクに飛べる、となっていたい。

hoverすると見出しの横にリンクアイコンが出て見出しに飛べる

ということで、自分のブログで同じことができるようにしてみた。以下の記事で試せる。

masawada.hatenablog.jp

見出しにカーソルをあわせるとリンクアイコンが表示される

以下のコードを 設定 > 詳細設定 > headに要素を追加 に貼って保存することで利用できる。テーマによってデザインなどは変える必要があるかもしれない。各々の環境にあったようにカスタムされたい。あとレスポンシブ環境では試していない。

gist.github.com

リンクアイコンはFont Awesomeから持ってきていて、アイコンSVGのライセンスはCC BY 4.0なので留意されたい。

fontawesome.com

他の部分はMITライセンスとした。

過去(おそらく8月中旬より前?)の記事については再度保存しないとidが挿入されないようなのでこちらも注意されたい。新しく書く記事については問題なく挿入されている。


長い記事を書いて見出しをつけたときに便利です。よければご利用ください。

AWS CLIでSwitch Roleするパターン

AWSアカウントを組織で管理していると複数アカウント利用するケースは多いかと思う。別のアカウントに切り替えるには、WebコンソールからSwitch Roleすればよい。そして以下のように $HOME/.aws/config$HOME/.aws/credentials を設定すればAWS CLIからもSwitch Roleできる。

$ cat $HOME/.aws/credentials
[main-account]
aws_access_key_id = ACCESS_KEY_ID
aws_secret_access_key = SECRET_ACCESS_KEY

$ cat $HOME/.aws/config
[profile sub-account]
source_profile = main-account
role_arn = ROLE_ARN
mfa_serial = MFA_SERIAL_ARN
region = ap-northeast-1

$ aws s3 ls --profile sub-account
(sub-accountのS3 bucketのリスト)

ただこれだと、 ACCESS_KEY_IDSECRET_ACCESS_KEY を平文で保存することになりやや脆弱なのでenvchainを使いたい。envchainはmacOSのKeychainやLinuxのGNOME Keyring等で暗号化保存したcredentialsを復号して環境変数に設定してくれる。使い方はREADMEの通り。

github.com

envchainを併用する場合 $HOME/.aws/credentials$HOME/.aws/config を以下のように設定すればSwitch Roleできる。

$ cat $HOME/.aws/credentials
(envchainに寄せたのでcredentialsは空)

$ cat $HOME/.aws/config
[profile sub-account]
credential_source=Environment
role_arn = ROLE_ARN
mfa_serial = MFA_SERIAL_ARN
region = ap-northeast-1

$ envchain aws-main-account env
...
AWS_ACCESS_KEY_ID=ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY=SECRET_ACCESS_KEY
AWS_DEFAULT_REGION=ap-northeast-1

$ envchain aws-main-account env aws s3 ls --profile sub-account
(sub-accountのS3 bucketのリスト)

$HOME/.aws/configcredential_source=Environment を足しておかないと Partial credentials found in assume-role, missing: source_profile or credential_source というエラーが出るので注意。また、profileの指定は --profile オプションでのみ可能で、環境変数 AWS_PROFILE で指定することはできない。このあたりはドキュメントにも載っている。

awscli.amazonaws.com

ところでこの方法だと $HOME/.aws/cli/cache/*.json に一時的なcredentialが吐き出されてしまい、envchainを使う意図としてはやや片手落ちな感がある。ではどうするかというと、AssumeRoleのコマンドを手で発行して、返ってきたcredentialを環境変数に設定する。具体的な方法は以下の記事が詳しい。

dev.classmethod.jp

自分の場合は以下のようなラッパーを書いて利用している。

github.com

このように使う:

$ cat $HOME/.aws/config
[profile sub-account]
role_arn = ROLE_ARN
mfa_serial = MFA_SERIAL_ARN
region = ap-northeast-1

$ envchain aws-main-account env aws-switch-role sub-account
Enter MFA code for MFA_SERIAL_ARN:
$ (sub-account) aws s3 ls
(sub-accountのS3 bucketのリスト)

やっていることとしては aws sts assume-role で取得したcredentialを環境変数に設定して $SHELL を新しく立ち上げているだけ。一時的なcredentialはこのプロセス内でのみ有効になるので、平文で保存されるよりは幾らかマシということにしている。(2022-08-12 追記: sudo cat /proc/$PID/environ | sed 's/\x00/\n/g' とかすれば読み取れてしまうので気持ちの問題ではある…)

ところでこの方法だとcredentialを環境変数に設定するのでAWS CLIの利用時にprofileを指定する必要がなくなるが、逆に現在どのprofileに対して操作しているのかが分かりづらくなる。そこで自分は $SHELL を立ち上げるときに本来必要ない環境変数 AWS_PROFILE を一緒に設定してあげて、これが設定されていたらプロンプトの表示を変えている。

$ cat $HOME/.zshrc
...
PROMPT="%{${fg[yellow]}%}%(!.#.$) $([[ -n $AWS_PROFILE ]] && echo "($AWS_PROFILE) ")%{$reset_color%}"
...

立ち上がったシェルを終了すれば元に戻れるので、一時的にセッションを張る使用感になる。


現実的にはひとつめのパターンやふたつめのパターンで十分ということもありそう。社のセキュリティーポリシーや自分のセキュアにしたい気持ちと相談して選択されたい。

1秒おきになんかする

ちょっと前の話だけど、社内のISUCON練習会で特定のエンドポイントが重いのをなんとかしようとしていた。このエンドポイントはキャッシュして問題ないので普段はキャッシュから返して1秒おきにリフレッシュしたい。Redisなどに入れてTTLを指定してキャッシュが揮発していたら再生成という手もあるが、これだとTTLが切れた瞬間わずかにリクエストが詰まってしまう。なので、何か別の手立てで定期的にキャッシュをリフレッシュしたい。

Goだとcarlescere/schedulerを使えば簡単にできそう。ただ、この回はPerlでやろうということで進めていた。AnyEventを使えばなんとかなる? と思いつつあんまり慣れていないライブラリを突然使うのはコストが高い。そんなときwatchを使えばいいじゃんということに気付いた。

systemdのunitファイルを以下のような感じで書いて systemctl start すれば良い。watchで1秒おきにcurlを起動してキャッシュの再生成エンドポイントを叩く作戦。

[Unit]
Description=Refresh cache every second

[Service]
Type=simple
Environment=TERM=linux
ExecStart=watch -n1 "curl -s http://localhost/refresh-cache"

[Install]
WantedBy=multi-user.target

watchはcurses的なやつが起動するので、 Environment=TERM=linux しておかないと Error opening terminal: unknown. というエラーが出る。

ところでsystemdにはtimerがあり、これも秒ごとに実行することができる。あとで思い出して試したところ、タイマーの精度が悪いのか実行が抜け落ちてしまうことがあった(AccuracySec=1us とかにしてもだめだった、なんででしょうね)。ということでwatchくらいが手軽でよさそうではないか。なかなか使うこともないだろうけれどメモ。


追記(2022-08-09):

1秒おきになんかする - あんパン

while true; do sleep 1; curl ….; doneとかはどうでしょう

2022/08/06 01:40
b.hatena.ne.jp

確かにwhileで回すのも良さそうですね。結果が標準出力に出るのでjournalctlなどで様子を観察しやすいのも良さそう。

技術書は出版社の直販サイトでPDFを買っている

よくKindleでセールやってる! 50%オフ! 50%ポイント還元! ということがあるけれど、全部無視して出版社のサイトでPDFを購入している。

  • DRMがかかっていない
    • メールアドレスがPDFのページに刻印されたりはある
  • 好きなリーダーで読める
    • 自分の管理方法は後述
  • 出版社に一番還元できる
    • と勝手に思っている

あたりが理由。

購入できるサイト

あとは技術書典やBoothなどには同人系もありそう。

逆に購入できないところで大手だとMdNとかSBクリエイティブなどがある。これらはKindleで購入するしかない。自分はKindleで買うのはいやだなと思って紙で買っている…… (しかしマンガはだいたいKindleで買っている)

どう読むか

Google Driveに入れてiPadのAcrobat ReaderにGoogleアカウントを紐付けて読んでいる。

iPad miniでリストを表示した様子

なぜAcrobat Readerかというと

  • 下手なリーダーよりはAcrobat Readerの方が使いやすい
    • 純正なので
    • 一応自分で注釈入れたりもできるけどあんまり使ってない。気になったところはプライベートのScrapboxに転記している
  • Acrobat ReaderにはGoogle Drive連携があり、Google Driveに放り込んでおけば自動で同期される
    • Dropbox連携もあるのでDropbox派の人はそれでもOK
  • Acrobat Reader自体はiOSでもAndroidでも配布されているので、iPadでもAndroidタブレットでもだいたい同じ体験で読める
    • ただし、Google Drive連携はGoogle Play 開発者サービスが存在しないAndroidタブレットでは利用できない
      • Kindle Fire系のタブレットでは利用できなかった
      • BOOXでは利用できた

という意図。他の人の暮らしも知りたい。