Shogo's Blog

Jun 22, 2023 - 2 minute read - github

GitHub Actionsの利用量をまとめる

GitHub Actionsの利用量はsettings/billingから確認できます。 それはいいんですが、問題は今月分しか確認できないこと! 「先月は〇〇分使ったから上限いくらに設定しておくか〜〜」ということができません。 APIは見つけたので、取得スクリプトを組んでみました。 Get GitHub Actions billing for an organization 集計スクリプト GitHub REST APIをたたいて、結果をGoogle Spreadsheetにまとめます。 GitHub REST APIを叩く部分はGitHub CLIを使えばすぐにできるんですが、 Google Spreadsheetへの書き込みをシェルスクリプトで組むのはちょっと大変です。 今回はGoで書いてみました。 package main import ( "context" "encoding/json" "fmt" "io" "log" "net/http" "os" "time" "google.golang.org/api/sheets/v4" ) func main() { ctx := context.Background() token := os.Getenv("GITHUB_TOKEN") if token == "" { log.Fatal("GITHUB_TOKEN is required") } sheetID := os.Getenv("SHEET_ID") if sheetID == "" { log.Fatal("SHEET_ID is required") } org := os.

Jun 22, 2023 - 3 minute read - go golang

Go 1.22で導入されるforループ変数の変更

Go 1.21 Release Candidateで、 forループ変数のセマンティクス変更の予定をしりました。 導入の背景や影響について、WikiのLoopvarExperimentで説明されています。 地味にインパクトが大きそうだったので、内容を理解するために和訳しました。 といっても訳の大半はChatGPT ChatGPT May 24 Versionのものです。便利。 多少僕の修正も入ってます。 以下LoopvarExperimentのリビジョンdce06fbの和訳です。 Go 1.22では、Goチームはforループ変数のセマンティクスを変更し、繰り返し毎のクロージャやゴルーチンにおける意図しない共有を防止することを検討しています。 Go 1.21には、この変更の予備的な実装が含まれており、プログラムをビルドする際にGOEXPERIMENT=loopvarを設定することで有効になります。 変更の影響を理解するのに協力していただける方々には、GOEXPERIMENT=loopvarを使用して試してみていただき、遭遇した問題や成功した点についてご報告いただけると幸いです。 このページでは、変更に関するよくある質問にお答えします。 この変更を試すにはどうすればいいですか? Go 1.21を使用して、以下のようにGOEXPERIMENT=loopvarを設定してプログラムをビルドします。 GOEXPERIMENT=loopvar go install my/program GOEXPERIMENT=loopvar go build my/program GOEXPERIMENT=loopvar go test my/program GOEXPERIMENT=loopvar go test my/program -bench=. ... この問題はどのようなものですか? 以下のようなループを考えてみましょう: func TestAllEvenBuggy(t *testing.T) { testCases := []int{1, 2, 4, 6} for _, v := range testCases { t.Run("sub", func(t *testing.T) { t.Parallel() if v&1 != 0 { t.

Jun 18, 2023 - 3 minute read - github

GitHub経由で脆弱性報告してみた

lestrrat-go/jwxに脆弱性を発見したので報告しました。 GHSA-rm8v-mxj3-5rmq Potential Padding Oracle Attack Vulnerability 「メールでやり取りするの面倒だなー」と思っていたら、いつのまにかGitHub経由で脆弱性報告できるようになってるじゃないですか。 Privately reporting a security vulnerability というわけで試してみたお話です。 背景 脆弱性報告の難しさ 脆弱性に関する情報は悪い人に悪用される可能性があるので、GitHubのIssueで報告するのは厳禁です。 公開レポジトリのIssueは広く公開されているので、悪い人に見つかってしまいます。 そのため、基本的に脆弱性の報告者はメンテナーと直接やり取りをする必要があります。 しかし、やり取りの方法に決まったルールはありません。 GitHubではセキュリティーポリシーをSECURITY.mdに記載するルールになっているので、運が良ければSECURITY.mdに連絡先が書いてあります。 Adding a security policy to your repository 運が悪ければ連絡先を頑張って探すところからはじめなければなりません。 まあ、たいていは連絡先としてメールアドレスが見つかるので、そこにメールを送ることになります。 ただし、メールというものは脆弱性の報告に特化したものではないので、どうやって情報をやり取りするかお互いに工夫が必要です。 僕はやったことないですが、修正のパッチをメーリングリストに送るんですかね。 大変そうです。 脆弱性と聞けば、CVEのような脆弱性情報データベースや、IPAの脆弱性関連情報の届出受付を思い浮かべるひとも多いでしょう。 共通脆弱性識別子CVE概説 - IPA 魚拓 脆弱性関連情報の届出受付 - IPA 魚拓 しかしこういった制度も、メンテナーの連絡先を管理しているわけではありません。 メンテナーの連絡先を探す手間も、メンテナーとのやり取りをする手間もかわりません。 (まあやったことないけど) 実際に報告した人のレポートにもありますが、「虎の威を借る」効果は多少期待できるでしょう。 CVEやIPAの名前だけ知っているというひとは多いでので、優先度を上げてくれるメンテナーも多いと思います。 脆弱性情報をIPAへ報告して修正されました #情報処理安全確保支援士 アカネちゃん、JVNに謝辞が載る:こうしす! こちら京姫鉄道 広報部システム課 @IT支線(17) - @IT 逆に言えば、脆弱性レポートの段階では、その程度の効果しかありません。 脆弱性の概要 lestrrat-go/jwxのJWEのデコード機能を利用する場合に、本脆弱性の影響を受ける可能性があります。 AES-CBCで暗号化されたデーターを復号するにはパディングを取り除く必要があります。 このとき不正なパディングを見つけた場合に “failed to generate plaintext from decrypted blocks: invalid padding” というエラーを返す実装になっていました。

May 29, 2023 - 2 minute read -

なぜタイムスタンプをIDとして扱ってはいけないのか

背景 マイナンバーカードの導入により、今まで役所で行っていた証明書の発行手続きを、コンビニに行えるようになりました。 このコンビニ証明書交付サービスにおいて、2023年5月9日誤って他人の戸籍全部事項証明書が発行されてしまうバグが明らかになりました。 開発元である富士通Japan株式会社は、この原因について以下のように説明しています。 川崎市様における証明書誤交付ついて(お詫び) 本事象の原因は、2か所のコンビニで、2名の住民の方が同一タイミング(時間間隔1秒以内)で証明書の交付申請を行った際に、後続の処理が先行する処理を上書きしてしまうことによるものです。 「時間間隔1秒以内」という条件から、 Twitterを始めとしたSNSでは「タイムスタンプ(秒)をIDにしているのでは?」という憶測が広まりました。 (もしくはIDに類するもの) ファイル名が秒単位の時刻なので、1秒間に複数申請があれば、後の申請の出力に上書きされてしまう、ということなのか。どうしてこれでうまくいくと思ったのか>富士通Japan https://t.co/FOvWWMdqar — Haruhiko Okumura (@h_okumura) May 10, 2023 「そんなことやるわけないじゃん」とは思ったのですが、自分自身はともかく周りのひとは・・・?と考えたら心配になってきました。 そういうわけで、なぜタイムスタンプをIDとして扱ってはいけないのか、注意喚起することにしました。 もう話のネタとして旬は過ぎた感はあるけど、文章に残しておくことが大事なんだ。 なぜタイムスタンプをIDとして扱ってはいけないのか さて、「秒単位のタイムスタンプをIDに使う」という設計がなぜダメなのか考えていきましょう。 なお、今回の証明書誤交付の原因が「秒単位のタイムスタンプをIDに使ったため」と主張する意図はありません。 証明書発行システムの実装を例として、秒単位のタイムスタンプをIDに使った場合にどうなるか?という思考実験です。 実在のシステムとは関係ありません。 誕生日のパラドックス ダメな理由として挙げられるのは誕生日のパラドックスでしょう。 誕生日のパラドックス - Wikipedia たとえば、小中学校のクラスに同じ誕生日のペアがいたら、珍しいこともあるもんだ!と感じませんか? 実はそんなに珍しいことではないというのが誕生日のパラドックスです。 クラスに23人いれば、その中に「同じ誕生日である二人組」が50%以上の確率で存在します。 誕生日のパラドックスを証明書発行システムに当てはめて考えてみましょう。 ユーザーがいつ証明書発行を行うかわからないので、ユーザーは一年の中のランダムな時刻に証明書発行を行うと仮定します。 年間n人のユーザーが利用した場合にIDが重複する確率は、以下のプログラム(雑)で計算できます。 # python n = 60*60*24*365 p = 1.0 for i in range(n): p = p * (n - i) / n print(i, 1-p) 実行してみると年間6612人利用でIDが重複する確率が50%を超えます。 一年が3153.6万秒あることを考えると随分と少ないことがわかります。 ... 6610 0.49986985152463326 6611 0.49997469552550755 6612 0.5000795334032722 6613 0.

Apr 23, 2023 - 4 minute read - go

RE: Akamai x UNIQLOコラボTシャツに書かれたプログラムを解読してみる

CDNサービスで有名なAkamaiがユニクロとコラボしてTシャツを作りました。 本日、Akamaiは @UNIQLO_JP のチャリティTシャツプロジェクト「PEACE FOR ALL」に参画したことを発表4月21日(金)より グローバルで発売されます。このデザインには人々の安全、安心を守りたいというAkamaiの願いが込められています。https://t.co/HVxINmoEzd#AkamaiPeaceForAll #Uniqlo #アカマイ pic.twitter.com/dIS9YOQVZM — アカマイ・テクノロジーズ (@akamai_jp) April 14, 2023 完全に二番煎じですが、Tシャツに描かれたコードを解読してみます。 Akamai x UNIQLOコラボTシャツに書かれたプログラムを解読してみる 解読してみる Tシャツに描かれたこのコード、PEACE FOR ALLに参画するために作られたのではなく、企業ブランドの一部として作られたもののようです。 Akamaiのウェブページをよく見てみると、背景にも同じコードが使われています。 コードの文脈をまったく意識せず切り貼りしたため、Tシャツのデザインでは失われてしまった部分があります(内容を理解できる人間にとってはちょっと残念)。 しかし、営業資料っぽいPDFに同じコードが利用されており、ここからなら十分に復元可能です。 クラウド投資のリターンを最大化 - Akamai EコーマスEマガジン 行ごとに分割して、同じ文字列が出現する箇所をつなぎ合わせると、以下のようなコードが浮かび上がります。 package main; import ( "fmt"; "html"; "log"; "net/http"; "strconv"; "strings"; "time" ); type ControlMessage struct { Target string; Count int64; }; func main() { controlChannel := make(chan ControlMessage);workerCompleteChan := make(chan bool); statusPollChannel := make(chan chan bool); workerActive := false;go admin(controlChannel, statusPollChannel); for { select { case respChan := <- statusPollChannel: respChan <- workerActive; case msg := <-controlChannel: workerActive = true; go doStuff(msg, workerCompleteChan); case status := <- workerCompleteChan: workerActive = status; }}}; func admin(cc chan ControlMessage, statusPollChannel chan chan bool) {http.

Mar 29, 2023 - 3 minute read - homebrew mysql

Homebrewで過去のバージョンのMySQLクライアントをインストールしたい

背景 Amazon Aurora(MySQL互換)のダンプを取ろうとしたところ、以下のメッセージが表示されてうまくいきませんでした。 % mysqldump hogehoge --skip-column-statistics --single-transaction --default-character-set=utf8mb4 mysqldump: Couldn't execute 'FLUSH TABLES WITH READ LOCK': Access denied for user 'root'@'%' (using password: YES) (1045) AWS RDSとMySQL 8.0.32の組み合わせが悪いらしく、同じ症状の人がいました。 AWS RDSにmysqldump: Couldn’t execute ‘FLUSH TABLES WITH READ LOCK’: Access denied for userが出て接続できなくなった mysqldump has incompatibile change in MySQL 8.0.32 手元のmysqldumpのバージョンを確かめてみると、思いっきり影響を受けるバージョンですね。 mysqldump Ver 8.0.32 for macos13.0 on x86_64 (Homebrew) MySQL 8.0.33で修正される見込みのようですが、2023年3月29日現在未リリースです。 リリースサイクルをよく把握してないですが、MySQL 8.0 Release Notesを見る限り、 1, 4, 7, 10月のリリースのようですね。 4月まで待てば解決・・・なんですが、そこまで待っていられないので、MySQL 8.0.31へダウングレードすることにしました。

Mar 24, 2023 - 2 minute read - git github

GitHubに接続したらWARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!と怒られる件

TL;DR SSH経由でGitHubに接続したら、以下のメッセージが表示されました。 % ssh -T github.com @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY! Someone could be eavesdropping on you right now (man-in-the-middle attack)! It is also possible that a host key has just been changed. The fingerprint for the RSA key sent by the remote host is SHA256:uNiVztksCsDhcc0u9e8BujQXVUpKZIDTMczCvj3tD2s. Please contact your system administrator. Add correct host key in /Users/shogo.

Jan 2, 2023 - 1 minute read -

「全人類兎化計画」の特設サイトがサブドメインで展開していてエラい

「全人類兎化計画」がエラいと思ったのでメモとして残しておきます。 サブドメインで公開していて偉い https://t.co/gA7pxJK5iA — f96fd3a0-bdb9-4f10-b69f-8f765c1d341c ICHINOSEShogo (@shogo82148) January 1, 2023 こういう特設サイトを公開するときは、新しいドメインをとりがちですが、「全人類兎化計画」の特設サイトのドメインは hololivepro.com のサブドメインになっています。 「全人類兎化計画」の特設サイトも公開中! 🔽特設サイトはコチラ🔽https://t.co/po5ocM1VQ6#全人類兎化計画 #兎田ぺこら #ホロライブ — ホロライブプロダクション【公式】 (@hololivetv) January 1, 2023 ドメインは企業の貴重な財産なので、きちんとした管理が必要です。 うっかり手放すとフィッシング詐欺に利用されたり、アダルトサイトに改変されたりするので、一度ドメインをとったら永遠に管理し続けなければなりません。 管理対象が増えると管理も大変です。 一方サブドメインなら、廃止しても他人に取られることはありません。クローズ時に考慮することが減るので楽ちんです。 ホロライブプロダクションのコンテンツは、LPサイトも含めてすべて hololivepro.com のサブドメインになっていますね。エラい! 全人類兎化計画|ホロライブプロダクション rabbit-plan.hololivepro.com hololive SUPER EXPO 2023 & hololive 4th fes. Our Bright Parade Supported By Bushiroad hololivesuperexpo2023.hololivepro.com hololive(ホロライブ)公式サイト | ホロライブプロダクション hololive.hololivepro.com HOLOSTARS(ホロスターズ)公式サイト holostars.hololivepro.com hololive production OFFICIAL SHOP [ホロライブプロダクション公式ショップ] shop.hololivepro.com ハイスクール・ホログラフィ|ホロスターズ highschool-holography.hololivepro.com みんなにも真似してほしいので紹介しました。 悪い見本はよく話題になるんですが、実際にサブドメインを利用している例はあまり見ないので。 ところで「全人類兎化計画」とはいったい・・・。

Jan 1, 2023 - 2 minute read - go golang

GolangでQRコード、マイクロQRコード、rMQRコードのジェネレーターを作った

GolangでQRコード、マイクロQRコード、rMQRコードのジェネレーターを作りました。 shogo82148/qrcode 作った理由は、「QRコードの復元能力はどういうマジックなんだろう?」と昔から気になっていたからです。 エンコードの方法は分かったものの、なぜ復元できるのかはわからぬままですが・・・。 また、2022年5月に発表されたrMQRコードにも対応しています。 デンソーウェーブ、細長く狭いスペースにも印字できる 長方形型の新しいQRコード「rMQRコード」を開発 使い方 qrcode.Encodeにバイト列を渡すと、 QRコードの画像をimage.Imageとして返します。 あと通常の画像と同じように扱えるので、image/pngなどで書き出してください。 package main import ( "bytes" "image/png" "log" "os" "github.com/shogo82148/qrcode" ) func main() { img, err := qrcode.Encode([]byte("Hello QR Code!")) if err != nil { log.Fatal(err) } var buf bytes.Buffer if err := png.Encode(&buf, img); err != nil { log.Fatal(err) } if err := os.WriteFile(filename, buf.Bytes(), 0o644); err != nil { log.Fatal(err) } } QRコードは日本生まれの規格なので、漢字を効率的に格納するモードがあります。 JIS X 0208の範囲内にある文字は自動的に漢字モードになります。 package main import ( "bytes" "image/png" "log" "os" "github.

Dec 25, 2022 - 1 minute read - perl

Perlのmodule_trueフラグを先取り!

Perl Advent Calendar 2022に穴が空いてしまったときの 穴埋め用に温めていた記事です。 無事完走したので公開してしまいます。 v5.38からmodule_true feature pragmaというのが入る予定らしいので試してみました。 v5.38は未リリースなので、開発版のv5.37.5で検証しています。 今まで挙動 Perlモジュールの末尾に1;という謎の記述を見たことはありませんか? # SomeModule.pm package SomeModule; sub import { warn "You imported a module!\n"; } 1; どこかに代入しているわけでもないので、ムダな一行に見えます。 しかしこの一行がないとモジュールの読み込みに失敗する場合があります。 以下のように1;を削除して、このモジュールを読み込んでみましょう。 # SomeModule.pm package SomeModule; sub import { warn "You imported a module!\n"; } # program.pl use FindBin; use lib "$FindBin::Bin"; use SomeModule; $ perl program.pl SomeModule.pm did not return a true value at program.pl line 3. BEGIN failed--compilation aborted at program.pl line 3.