書いたンゴ
Secure by Designを読んだ
社内で設計に明るい方がオススメされていたので読んでみました。
この生成 AI 時代では勝手にセキュアなデータがコミットされてしまっていたり、インジェクション攻撃が可能なコードが知らぬ間に実装されてしまっていたりと、よりセキュリティに対して意識を強くもたねばなりません。
かなり分厚い書籍ですが、翻訳書に多い海外のジョークや癖のある言い回しもほとんどなく、簡潔な表現がされており読みやすかったです。

Secure by Design
タイトルにもなっている「Secure by Design」とはセキュリティを高める設計(デザイン)を指していました。どうしてもセキュリティの対策は後回しになりがちで、セキュリティ診断サービスを受けたり、考えたくもないですが、実際に攻撃を受けてからインシデントとなり、結果的にセキュリティの重要さに気づくことがあります。開発とセキュリティ対策が分離されるのが従来のやり方であり、実際に求人を見てみると、開発エンジニアとは別にセキュリティエンジニアが募集されているケースが多いです。
著者達はこの現状を問題だと考えており、解決のために「Secure by Design」を提唱しています。Secure by Design を実践することで、開発とセキュリティが分離せず、自然と高いセキュリティをもったコードが実現されていくとのことです。
ドメイン駆動設計をする
どのように Secure by Design を実現するのか?という問いに対してドメイン駆動設計が登場してきます。 ドメイン駆動設計ではドメイン知識を値オブジェクトやエンティティといったモデルとして定義することで、ドメイン知識をコードへそのまま反映させます。すでに各所で値オブジェクト・エンティティの解説があるので、こちらでは省略します。
さて、どのようにドメイン駆動設計がセキュリティと関わってくるのでしょうか。
次のコードは、ユーザー名とメールアドレスを受け取り新規ユーザーを作成する API の実装です。ドメイン駆動設計では、知識や制約をきちんとモデル化する事が重要ですが、このコードではユーザー名とメールアドレスは、ただのStringとして扱われています。
// POST: /users に対応するサービス class UserService { fun createUser(name: String, email: String): User { val connection = DriverManager.getConnection("jdbc:mysql://localhost/mydb", "user", "pass") val statement = connection.createStatement() val sql = "INSERT INTO users (name, email) VALUES ('$name', '$email')" statement.executeUpdate(sql) return User(name, email) } }
ただのStringだということはメモリ容量に収まる限り、あらゆるどんな文字列であっても制限なく受け入れてしまいます。
この仕様を悪用すれば SQL インジェクションや、巨大な文字列をリクエストして DB をダウンさせたりといった攻撃ができてしまいます。つまり、攻撃が成り立ってしまうのは、悪意のあるリクエストがどこでもブロックされていないからです。
悪意のあるリクエスト
{ "name": "山田'); DROP TABLE users; --", "email": "aaaaaaaaaaaaaaaaaaa...@example.com" }
INSERT INTO users (name, email) VALUES ('山田'); DROP TABLE users; --', 'aaaaaaaaaaaaaaaaaaa...@example.com')
プリミティブ型をそのまま使わない
ユーザ名とメールアドレスをStringで定義するべきなのか?というのが、ドメイン駆動設計で何度も問われていることです。
メールアドレスには国際標準規格があります。ユーザー名はどうでしょうか。このサービスのコンテキストでは、ユーザー名に記号を使えない・最大 100文字のような制限があるかもしれません。こういった知識・制約をコードに正しく反映させてモデル化することで、自然とコードは堅牢でセキュアな実装となっていきます。
ドメインプリミティブ
本書では知識・制約を正しく反映させた値オブジェクトのことをドメインプリミティブと定義しています。
試しにユーザー名をドメインプリミティブとして定義するとこんな感じでしょうか。記号は使えず 100文字以内の制約が表現されました。この時点で、先ほどの SQL インジェクションと巨大データのリクエストでユーザー名のインスタンスを作ることは不可能になりました。後続の書き込み処理でUserNameを扱うようにすれば、攻撃をブロックすることができます。
@JvmInline value class UserName private constructor(val value: String) { companion object { // 英数字、ひらがな、カタカナ、漢字、スペースのみ許可 private val ALLOWED_PATTERN = Regex("^[a-zA-Z0-9\\p{IsHiragana}\\p{IsKatakana}\\p{IsHan} ]+$") fun of(value: String): UserName { require(value.isNotBlank()) { "ユーザー名は空にできません" } require(value.length <= 100) { "ユーザー名は100文字以内にしてください" } require(ALLOWED_PATTERN.matches(value)) { "ユーザー名に使用できない文字が含まれています" } return UserName(value) } } }
インフラや設定で守るべき箇所はどうするのか
Infrastructure as Code (IaC)や継続的なCI/CD パイプラインなど、近年では当たり前となった手法が紹介されていました。
イテレーティブな開発の中に侵入テストや脆弱性診断などを取り組み、短いスパンで発見・学習をできる仕組みづくりをすることが推奨とされていましたが、特に目新しいトピックはなかったのかなと思うので、気になる方は実際に目を通してみてください。
詰まる所
これはセキュリティの本というよりもドメイン駆動設計の本です。
本書のおもしろい点は、従来から広く支持されているドメイン駆動設計にセキュリティの観点を組み合わせている点です。自分も今まで考えたことがなかったのですが、言われてみると確かにな...と感じました。一方で、ドメイン駆動設計をすでに知っている前提で書かれているのと「プリミティブ型をそのまま使わないで〜」という一貫した主張を 500P ほどのボリュームを使って書いているので、この本を真っ先に読んだ方が良いよ!とは思いませんでした。
しかし、冒頭でも書いた通り生成AI が著しいこの時代こそ、セキュリティに関心を持ち Secure by Design でセキュアなコードを書く意識は重要さを増しています。
実装が楽になった分、ドメインプリミティブを使ったコードを生成させるようにしたいですね。そのためにはドメインエキスパートの会話が不可欠です。ここは結局、サボれないので、今日も今日とてドメインに向き合っていきたい。
4月の振り返り
もう暑い...
春はどこへ行ってしまったのかと思いきや、急に冷える日もあり服装に迷う日々です。
ありがたいことに体調を崩すこともなく元気に過ごしています。ギリ汗をかかない心地よい気温なので散歩が捗るのですが、少し前に話題になったセブンイレブンの紅茶マシーンが家の近所?(徒歩30分)にも設置されて、定番の散歩コースになりつつあります。数百円でこのクオリティーはすごい。

4月度の成果
品質
- 専門的なテスト知識の獲得 - アプリケーション品質の向上 - E2E テストの棚卸し(Flaky テストの撲滅とテストピラミッドのバランシング) - リグレッションテストの再設計(初期のものから更新ができていない) - テスト戦略の定義・チームでの合意 - テストガバレッジの確立(品質の数値化を検討)
先月の振り返りに記載した通り、体制が変わったことで別部署がオーナーをとる形になりました。
引き続き安全で高品質な開発を続けていきたい気持ちですが、特別な成果物はありませんでした。感想は別の記事に書こうと思っていますが、社内で設計に強いメンバーから「Secure by Design」という書籍を紹介して頂き、こちらを読み進めています。
反省点
特にありません。
新年度の考えた品質へのコミットはある程度、達成したのかなと思います。JSTQB の資格も取れましたし、テストピラミッドのバランシングの方針を示して実施したことで、E2E テストの拡充とトレードオフについて社内で認知されるようになってきたのかなと感じています。生成 AI 時代ということもあり、従来の E2E テストサービスでは自由度が低く扱いが難しいため、自分の観測している感じだとplaywrightに移行する事例が増えています。一方、テストレポートや実行基盤の構築、メンテナンス(playwrightに限ったことではないですが)などの課題には向き合っていかねばなりません。
プロダクトと向き合う
- 複雑なドメイン知識と向き合う - 医療制度(特に負担額計算領域)の理解 - 知識をコードに落とし込む経験をより積む(eg: いわゆるDDDの実践的トライ) - 歴史あるコードとの向き合い知識の獲得 - レガシーコード改善ガイドを読む(購入済み) - 単体テストの考え方/使い方
今まで実装を始めようにも、期待値が不明なケース・なぜこの期待値になるのかの根拠を理解できない事が多かったですが、かなりドメイン知識が身についてきた成果なのか、詰まることが減りました。直近では労災の点数・負担額計算の開発をしており、どんなケースをサポートしないといけないのか・既存の健保の点数・負担額計算の処理を使いまわせるのかを判断んするために、改めてコードを読み直す機会が増えました。コードを理解するにあたって、今まで流し見程度だった厚生労働省が公開している資料を読み漁っています。
反省点
手を動かす際はコードファーストで実装から始めていましたが、ドメイン知識(制度や期待値)に詳しくないことで何度もバグを出してしまい遠回りしてしまいました。イテレーティブな開発をしているので、動く成果物を作る・見せるという観点では良かったのですが、レセコン開発では設計をミスるとあっという間にモデルが破綻してしまいます。 改めてドメイン知識を事前に得ることの重要性を感じましたが、ややディープな領域なので根拠のある情報を見つけるのが難しいという課題もあります。
総評
やることをやった1ヶ月でした。
労災の開発にフィットすることに全力投球をしたので、自発的な成果物を生み出せなかったのは反省点。ここには詳しく書けないですが、かなりバタバタと忙しい月でした。目標がやや形骸化してきているので、改めようと思います。せっかくの GW なので時間を確保したい。
お知らせ
近々、はてなブログから独自ホスティングのブログに移行しようと思います。
今まで「はてなブログ Pro」を使っていましたが、記事を有料サービスを使ってまで書くモチベーションがなくなりました。PV を狙った記事を書いていない(書く気もない)のと、生成 AI の影響かブログの PV が激落しておりGoogle Adsenceで「月の支払い額 < 収入」を実現できなくなりました。独自ドメインが使えるのと、広告が自由に配置できることをメリットに「はてなブログ Pro」を使っていましたが、あまり魅力ではなくなりました。
また、はてなの振込み詐欺事件のこともあり、この会社のサービスを使い続けることに不安も感じています。
3月の振り返り
ようやく過ごしやすい季節になってきましたね。
やや寒さを感じるものの、何枚も着込んで外に出ていたのが嘘のように暖かくなりました。すっかりと外の様子も変わり、早咲きの桜は散り、枝垂れ桜が花を咲かせていました。美しい...

3月度の成果
品質
- 専門的なテスト知識の獲得 - アプリケーション品質の向上 - E2E テストの棚卸し(Flaky テストの撲滅とテストピラミッドのバランシング) - リグレッションテストの再設計(初期のものから更新ができていない) - テスト戦略の定義・チームでの合意 - テストガバレッジの確立(品質の数値化を検討)
引き続きテストピラミッドのバランシングに取り組みました。 先月分と合わせて全体の 10% ほどを単体テスト化することで、E2E のクレジット削減・テストサイクルの高速化を達成することができました。 Flaky な E2E テストが削減されたことで管理のコストも減って万々歳です。特段、新しいことをやっていたわけではありませんが、地道に取り組んだことによって成果を感じられるようになりました。
反省点
一方で体制が変わったこともあり、テスト戦略やその他、施策に私が取り組む必要性が低くなってきました。
とはいえ、品質の可観測性を高めたいという思いがありましたが、ゴールのビジョンを描けておらずここまで目立った成果を上げることができませんでした。知見のない領域ではありますが、思いが先行して先走ってしまったことを反省しています。
(やる気があるのはいい事と思いたい)
プロダクトと向き合う
- 複雑なドメイン知識と向き合う - 医療制度(特に負担額計算領域)の理解 - 知識をコードに落とし込む経験をより積む(eg: いわゆるDDDの実践的トライ) - 歴史あるコードとの向き合い知識の獲得 - レガシーコード改善ガイドを読む(購入済み) - 単体テストの考え方/使い方
今まで得てきた知見が積もり積もって、本格的に不具合修正や機能追加に取り組みました。 実装面では Claude Code の活用や、テストファーストで再実施可能な状態を用意する工夫で、手が詰まることはあまりないと感じています。ただ、ドメインが難しすぎて、期待値が分からず手が止まるというケースが多いです。特に医療費の負担額を算出するケースでは、特例や特殊ルールが多く、これらが重なりあった場合、果たしてどうなるのか?を開発者だけの知識で判断することは困難を極めます。
宣伝
ここらへんの話を技術書典20 にて頒布される書籍に執筆しました。
情報が公開されて次第、こちらにも記載します。乞うご期待!
公開されました!
反省点
先ほどの話と関連しますが、何かを修正した時に全体の計算モデルとして破綻していないか?は常に気を付ける必要があります。 しかし、ドメイン知識がまだまだ弱いので、こういったケースでヨシ!の判断を自信を持ってすることができません。自分ができる事としては、知識を引き続きインプットしていくことと、テストを拡張してデグレを検知できる確率を上げることでしょうか。
総評
あっという間に 1Q が終わりました。
成果を感じている・そうではないものが明確に別れてきたので、自分の強みや興味関心が少し透けてきたのかなと思います。
品質に関しての具体的なアクションは前述の通り、減ってくるかなと思いますが、引き続きドメインにはしっかりと向き合っていきたい所存です。
以上です。
おまけ 最近やめたこと
わざわざ別記事にするほどの内容でもないので、ここに書いておきます。
バーベルスクワット
ある日のこと、膝に謎の違和感と痛みが...
真っ先に思いついたのは週に一度、取り組んでいるバーベルスクワットです。トレーニング中に膝からパキパキと音がすることがあって、痛みはなかったので気にしていなかったのですが、おそらく膝にダメージがあったのかなと思います。爆発力と扱える重量の観点では、バーベルスクワットに勝る種目はないと思いますが、膝の持続性を考えると微妙かも...と思い止めてみました。
とはいえ、下半身のトレーニングをしないのは嫌なので、メニューをゴブレットスクワットとブルガリアンスクワットに変更しました。なぜこの 2種目なのかは話すと長くなるので、興味があればコメントなどで教えてください🙏
エナジードリンク(清涼飲料)
シンプルに味が好きで週に一度ほど、飲んでいました。
ただ、明らかに体に悪いだろうなぁ...と自覚はあったので、控えるようにしてみた結果、肌荒れ・下痢の頻度が減ったと感じています。
気づいたら清涼飲料も飲まなくなっていました。ただ、どうしても飲みたくなった時は糖分の含まれていない炭酸水を飲んでいます。

