hkoba blog

プログラマーです。プログラミング言語ミーハーです。ツッコミ歓迎です。よろしくどうぞ(能代口調)

謹賀新年/2025目標

あけましておめでとうございます

昨年仲良くしてくださった皆様、ありがとうございました。

また本年もよろしくお願いいたします。

昨年の振り返り、良かったこと

  • 仕事
    • 職場のメインリポジトリーの gitlab self-hosted への移行とそれに伴うデプロイツール群の改定を(無理しつつも)やり終えたこと
    • OS移行後のサーバートラブルを乗り切れたこと
    • gcloud 操作などのコマンドラッパーを Tcl で書くときの定形が定まってきたこと。お陰で Cloud IAP の設営と撤去もスクリプト化して同僚に委ねられるようになったこと。
  • 生活
    • 父の死去に伴うあれこれを概ね乗り越えられたこと
    • 宮崎の暮らしで、自然を楽しむ以外に、宮崎駅近辺から西橘(ニシタチ)周りも少しずつ楽しめるようなりつつあること
    • 艦これアーケードのレイテ前編・後編それぞれを甲で突破して海峡章と捷号章を得られたこと

昨年の反省点や、残念だったこと

  • 職場において戦略と意志決定の共有が機能していなかったこと
    • そのしわ寄せがOS移行前の検証期間不足に繋がり、複数のサーバートラブルを長引かせてしまったこと
  • (それどころではなかったとはいえ)自作OSS方面の活動が低調だったこと。

今年の目標

  • Perl 、YATT、Tcl/Tk 各方面の活動の成果をもう少し他の方にも使ってもらいやすい形に近づける
  • 言語開発に関して、Tcl から得た着想を(実験言語でいいから)具体化する
  • 家の収納の整理。ものを探し回らなくて済むようにしたい

Plack middleware 書く時もJSON指向のOOモジュリーノが便利ですよ〜

この記事は Perl Advent Calendar 202420日目の記事です。


こんにちは、Perl でモジュリーノ書くようになって四半世紀の hkoba です。最近は艦これアーケードレイテ後編イベントが熱いです。

さて皆さんは Plack の middleware を開発する時、どのように開発を進めるでしょうか? 普通なら、簡易的な app.psgi を書いて、plackup -R でテストサーバーを起動して…という手順で進めることでしょう。あるいは plackup -e で頑張る人もいるかもしれません。どちらも、慣れた人なら全く手間に感じない手順かもしれません。でも、もっと直接的な方法…そう、そのモジュール自体をプログラムとして直接実行して試す方法は、無いのでしょうか?

この記事では、Plack middleware を JSON 指向のOO モジュリーノとして記述することで開発の try and error をコマンド行から直接行えるようにする方法を紹介します。

JSON 指向の、オブジェクト指向モジュリーノ(JSON Aware OO Modulino)とは

モジュリーノ(Modulino)とはライブラリー(モジュール)として使えると同時にプログラムとして直接実行できるような、そんなスクリプトファイルのことです。

オブジェクト指向(OO)モジュリーノ という単語は私が勝手に提唱している概念で、git や cvs などのサブコマンドを持った CLI コマンドの呼び出し規約をモジュリーノとしての挙動にマップする…つまり、

  • モジュールの各メソッドを CLI からサブコマンドとして呼び出すことが出来る
  • モジュールのインスタンスを new するときの引数をサブコマンド名の前の --name=value オプションで指定できる
  • CLI からメソッドを呼び出した時、戻り値はシリアライズされて標準出力に出力される

ようなモジュリーノです。

JSON 指向の OOモジュリーノ とは、

ものです。このように JSON 限定で コマンド行から Perl の HASH や ARRAY を安全に渡せる ようにすることで、モジュリーノとしてコマンド行から試せる事柄を飛躍的に増やすことが出来ます。詳しくは過去の紹介スライドをご覧下さい。

コマンド行で PSGI call を直接試せると、こんな風に嬉しいのです

Plack::Middleware が実装するべき APIcall メソッドです。 JSON 指向の OOモジュリーノなら、引数として $envjson で渡して呼び出せば、出力として PSGI tuple が得られるでしょう。

ここでは例として拙作の Plack::Middleware::Validate_Google_IAP_JWT をとりあげます。
(これは Google Cloud のゼロトラスト保護機能である Identity-Aware Proxy - IAP 保護下の Web アプリに組み込んで使う middleware で、Cloud IAP が HTTP ヘッダーに設定してくれた認証情報入り JWT に対して、それが正当なものかどうかを検証するためのものです。 うちの現場で1年以上使ってうまく機能しているので、先程 CPAN に公開しました)

まずは http://localhost/ をアクセスした場合を想定して、 $env->{PATH_INFO}/ を設定して呼び出してみましょう。 期待する HTTP Status は 403、Forbidden です。

% cd ./lib/Plack/Middleware
% ./Validate_Google_IAP_JWT.pm call '{"PATH_INFO":"/"}'         
[403,[],["Forbidden (no JWT assertion)\n"]]

次に、試しに偽の JWT を入れて試してみましょう。壊れたリクエストなので、 HTTP Status 400 (Bad request) を返すのが良いでしょう。

% ./Validate_Google_IAP_JWT.pm \
 call '{"PATH_INFO":"/","HTTP_X_GOOG_IAP_JWT_ASSERTION":"fake.foo.bar"}'        
[400,[],["JWS: invalid header part at ./Validate_Google_IAP_JWT.pm line 132.\n"]]

このモジュールには一部の path に guest アクセスを許す(JWT 検証をバイパスする)機能があります。これも試してみましょう。 この場合、middleware を通過した後のアプリケーションが無いとだめなので、ダミーの app を渡す機能を予め実装してあります。

% ./Validate_Google_IAP_JWT.pm \
 --app='[200,[],["OK"]]' --guest_subpath=/guest/ \
 call '{"PATH_INFO":"/guest/"}'
[200,[],["OK"]]

# 念のため、 / の Forbidden も確認
% ./Validate_Google_IAP_JWT.pm \
 --app='[200,[],["OK"]]' --guest_subpath=/guest/ \ 
call '{"PATH_INFO":"/"}' 
[403,[],["Forbidden (no JWT assertion)\n"]]

では最後に、実際の JWT を使って、検証が通るか調べてみましょう。call だと OK が返るだけで面白くないので、ここではこのモジュールの内部メソッド decode_jwt_env を呼び出してみます。

期限切れした JWT を渡した場合>

% ./Validate_Google_IAP_JWT.pm decode_jwt_env \
  '{"HTTP_X_GOOG_IAP_JWT_ASSERTION":"'$(<../../../t/sample.jwt )'"}'
JWT: exp claim check failed (1734493203/0 vs. 1734505329) at ./Validate_Google_IAP_JWT.pm line 132.

今現在有効な jwt を貼り付けた場合>

有効な jwt を decode_jwt_env に与えた結果

このように、JWT を正しくデコード出来るかをコマンド行から簡単に確かめることが出来ます。

まとめ

Plack の Middleware を書くときも JSON 指向な OO モジュリーノにしておくと開発がはかどりますよ、という話でした。 明日の記事は @teckl さんです。

ここまで読んで下さりありがとうございました〜

喪中につき年賀を失礼します/2024近況報告

昨秋、父が亡くなりました

喪中につき新年のご挨拶を失礼させていただきます。

旧年中に仲良くしてくださった皆様、ありがとうございました。

今年もよろしくお願いします。

宮崎に移住しました

また、皆様へのご連絡が遅れましたが、昨年半ばから東京を離れ宮崎へ移住をしております。きっかけは父の入院・闘病が始まったことでしたが、 移住を決断した理由は、母を独居にしてしまうと色々と心配が増えるためでした。兄弟の中では自分が最も身軽なので、ここはお兄ちゃんが頑張るしかあるまいと…長男ダカラー(お仕事自体はリモートで継続です)。東京で借りていたマンションもすでに引き払いました。

とはいえ移住にあたっての諸々はまだまだ続くので、当面は暮らしのペースを掴むことを最優先にしていこうと考えています。

宮崎はなかなか良いところです。機会が有ればぜひ遊びに来てください。

仮説:Twitter の広告ビジネスは(login ユーザーじゃなく)guest をターゲットにしたほうが、うまく機能するのではないか?

  1. 現在 Twitter はビジネスの持続性を得るため、 login 済みアカウントへのターゲット広告を主な収入源にしようとしている(のですよね?私はそう理解しています)

    • ゆえに、↑そのビジネスモデルに直接的には貢献しない bot API アクセスの料金プランを値上げした
    • その結果、スクレイピングが横行したので、guest/public read も禁止しようとしている
  2. しかし、Twitter がバズを生み出すハブ・プラットフォームとして社会的に唯一無二であった点は、その guest/public readability とソーシャルグラフとの掛け算の大きさにあったのではないか?

    • インフルエンサーが(他の blog などで長文を書いたあとで)twitter にリンクを投稿するのは、ここに乗せれば guest も含めて万人への timely な広報になるからだった。
    • どんな流行も、early adapter より遅れてくる(=話題に接する)人のほうが多い。遅れてくる人= guest、埋め込みなどで他のメディアで知る人と思って良いのでは。
    • guest/public read 切り捨ては、late majority の切り捨てであり、バズを生み出すハブとしての地位を自ら捨てるようなもの
    • 今すすめている閲覧制限は、自殺行為なのではないか?
  3. もし、late majority がほぼ guest でありバズの本体であるとするなら…広告は guest に対して出すほうが効果的なのではないか?

    • 例えば、tweet 埋め込みに対して広告を出す、など

まぁ、素人考えかもですが…

謹賀新年/2023目標

あけましておめでとうございます

旧年中に仲良くしてくださった皆様、ありがとうございました。
本年も変わらず元気で、日々を地道に生き抜き、暮らしを作っていきましょう

昨年の振り返り、良かったこと

  • 仕事

    • 業務で他社さまの営業の方とのオンラインミーティングの機会をもらえたこと。アカリクさん、GCP さん、どちらも打てば響く感じがあって、とても楽しかったです。ありがとうございました。

    • mermaid-js でシーケンス図を書く方法を覚えたこと。これで業務フローの聞き取り・整理がとてもはかどった

      mermaid.js.org

    • marp.appでスライドを書く方法を覚えたこと。マニュアルは mdbookで書いて、講習の資料は marp スライドで書く、みたいな使い分け。(次は slidev にも挑戦してみたい)

    • gitlab の活用を(徐々にだけど)拡大出来ていること

      • gitlab-ci → mdbook / marpで社内全員向けドキュメントやスライドを量産しやすくなった(apache + shell executor だけど)
      • cvstrac の ticket を gitlab の issue へと差分取り込みする手順を作れたことと、 GitLab Meetup でその発表を出来たこと hkoba.github.io
    • buildah を覚えたことで(Dockerfile じゃ困難なものでも)コンテナ化出来るようになったこと。下記の記事の Buildahとは何か?なぜ使うのか? と、別の記事に有った unshare コマンドの話 が大きなヒントになりました。

      rheb.hatenablog.com

    • stefafafan さんが記事で紹介してくれていた、IAP によるゼロトラスト保護にワイルドカード証明書を使う方法と、それを使って IAP 保護下で Cloud Run サービスを量産する方法を、概ねうちでも再現できたこと。

    • 逆terraform(terraformer)の導入。これで GCP の設定を tf ファイル群としてダンプすることが出来るので、クラウドの設定変更を git で履歴管理& gitlab issue への紐付けが可能になった。
  • プライベート

    • ほぼ健康に過ごせたこと
    • 夏コミ行けたこと
    • 観艦式2022 行けたこと!

      いずも
      もがみとあたご
      くにさき

    • SteamDeck ゲット!

    • (未完成で未だ他人様には勧められないけど)yatt-js の実装を大分進められたこと
      • typescript での開発のリズム的なものが、少しずつだけど、つかめつつあること

昨年の反省点や残念だったこと

  • いまだ javascript 周りのキャッチアップが終わらない(終わるのか?)
    • npm へのパッケージ公開のお作法的なもの、誰かに教わりたい・相談したい…命名とかバージョンどの程度から publish してよいかとか workspace とサブパッケージの分け方とか…
  • 外出が苦手になりつつあること…特に夜や冬場
  • 部屋の片付け、してないな…
  • 好きで通っていたご飯やさんが、辞めてしまったこと。コロナ禍ゆるすまじ
  • .oO(…身近なところで、食っていけないという話を聞いてしまった。ちょっと考えないと…)

今年の目標

  • yatt-js を生活か仕事に実戦投入し、それを通して他人様にも使ってもらえるレベルに育てる
  • No Code/Low Code DB の OSS、どれが使えそうか選定して活用を試みる
  • 嫁・彼女探しを…諦めない…
    (致命的な衝突をしないですむ人を、どうやって探せば良いのかしら…)

謹賀新年/2022目標

あけましておめでとうございます。

旧年中に仲良くして下さった皆様、ありがとうございました。本年もよろしくお願いいたします。

2021 振り返り、良かったこと

  • 仕事
    • 主要な業務サーバーの脱VPN・ゼロトラストセキュリティ化が出来たこと。
      具体的には GCP の IAP - Identity-Aware Proxy の導入

      cloud.google.com

      並びにその setup/teardown 手順をある程度はスクリプトに出来たことで、ゼロトラスト保護されたサーバーの量産が容易になったこと

    • ゼロトラスト保護された gitlab の導入と、 gitea, redmine からのデータ移行を実現できたこと
      標準の import 機能だけでは issue の取りこぼし、プルリク上の議論の取りこぼし、commit からのチケット参照が無視される件などで満足できず。gitlab のソースを解読・切り貼りして import 用 ruby スクリプトを書いて実現(実質初 ruby
      • 出来上がったスクリプト、公開はしたいけど、手法が手法だけに、適切な公開方法が分からない。アドバイス頂ければ公開できるかも…
  • プライベート

    • ほぼ健康に過ごせたこと
      新型コロナによる死は決して見知らぬ他人事ではない、そう思わされる出来事があり。 それゆえに、今後も己の身命を慎重に大事に使っていかねばならないなと。健康に過ごせたことを感謝しつつ、警戒を続けたい。(ウザがられるかもだけど…)

    • 艦これアーケードを続けられていること

    • yatt の typescript 版の実装を大分進めることができたこと(さきほど Public にしました)
      github.com

2021 の反省点

  • 運動不足・外出不足

  • 同僚とのコミュニケーション不足…害は有るはずだけど、自分にそれが見えてないのが危うい

2022 の目標

  • typescript 版 yatt を他人に使ってもらえるレベルに仕上げる&個人的な情報生活の道具として使い始めること

    • npm にどの段階で公開すべきか?誰か node 慣れした人にアドバイスをもらいに行きたい…
  • 友達作り?パートナー探し?

謹賀新年/2021目標

あけまして、おめでとうございます

旧年中に仲良くして下さった皆様、有難うございました。本年もよろしくお願いします。

2020 の良かったこと

2020 の反省点

  • 仕事
    • Gitリポジトリ管理の迷走。 phabricator → gitea へ移行したものの、グループ管理周りが不満で、全社導入には向かないと判明。
    • GCP 以外の部分に停滞感があったこと。優先順位的に仕方がなかったとはいえ…
    • 作ったツールを他の人に使ってもらうための、ドキュメントが書き足りない。
  • 生活
    • 運動不足。足が弱ってそうな気がする。
    • 視力低下。引きこもりだから。対策がほしい…

2021 の目標

  • GCP、まだまだ理解不足や設定自動化が出来てない部分が多いので、引き続き勉強してツール化を進める
  • GAS 力を付ける
  • yatt を typescript へ移植する