せてぃーずノート

Javaのイベント参加レポートとかを書いたりします。

JJUG CCC 2023 SpringでExposedについて話した反省会

久々のオフライン開催!

会場は以前よりは狭く、入れ替え制でしたが久々のオフライン開催でした。 やっぱりオフラインはいい。集中できる。 オンラインで聞いてるとついつい内職してしまうので・・・。

自分のセッションの反省会

今回の反省として、「解決するべき問題」が明確に存在しなかった点が挙げられます。 去年Testcontainersについてのテーマのときは「DBを使ったテスト」という聞いてくれる人の多くが課題として持っている(であろう)ものについての話でした。 なので、

今回のExposedではそもそもプロダクトに採用した理由が「既存のORM以外の選択肢を模索したい」といった動機でした。 多分聞きにきてくれる人も、Exposedって何という感じだったと思う。 全体的なテーマやストーリーが弱い話をしてしまったった感じがあります。

どうすればよかったか?

素直にExposedの紹介にもっと時間を割くべきだった。 Kotlinのライブラリだったので、コードや機能紹介を増やすと辛いかと思って、導入の背景を中途半端に詰め込んでしまった。 Kotlinを避けたにもかかわらず、「Null安全」などの概念を説明なしに使用してしまった点も問題だったとおもう。

もっと単純に「クエリを楽に書けて楽しい!SQL楽しい!ヒャッハー!」というポイントに焦点を当て話すべきでした。 結局それが伝えたかったテーマだったので。

自分の好きなものをお勧めするのはクッソ難しいなぁ・・・

その他反省

前日に飲み会があり、飲み過ぎ&食あたりだった(西新宿のトイレを20分占領するくらい・・・) 体調が悪くせっかく申し込んだ午後のセッションを家でオンラインで見ることになってしまった・・・。

次回は体調に気をつける。

JJUG_CCCでTestcontainersについて話してきた

スライドはこちら

speakerdeck.com

CFP出す→採択まで

過去何回かJJUG CCCに参加している中、ネタがあったらいつか喋ってみたいと思っていました。そんな時Testcontainersを使ってみてとても良いと感じたのでこれは話すネタなのでは思いました。

前回、前々回のJJUG CCCを調べてみたらTestcontainersのセッションがなかったので、出さないで後悔するより出して後悔ってことでダメ元でcfpを出してみました。

採択→スライド作成

採択されてしまったのでスライドの構成を考え始めました。持ち時間は15分だったので、導入からSpringへの組み込みまでを一通り紹介すれば時間ちょうどくらいという作戦で進めることにしました。

GW前にスライドは完成させようと思っていたが、急に仕事が忙しくなった&エルデンリングが楽しかった&とても面白いボードゲーム(Dune砂の惑星)を買ってしまったため作スライド作成はあまり進まない日々が続きました。(頭の中で色々考えてはいたけど、手を動かすのをサボりまくり・・・)

締め切りギリギリじゃないと真面目に始めないの良くない!

動画作成→リテイク

動画作成についてはこんな感じで作ってました

  1. keynoteで1〜2ページ喋る
  2. 動画に出力してiMovieに放り込んで結合
  3. 見返して気に入らないところを差し替え

収録日が変わってテンションが違うのは妥協・・・

とりあえず一通り作った後、知り合いのエンジニアに作成した動画を見てもらったところ「これ、ライブラリの使い方についてただ喋っているだけじゃん。公式HPみればいいんじゃない?知らんけど」という厳しいツッコミを受けました。

確かに言われてみればその通りだと思い、「とにかくこのライブラリは簡単!」というところを過剰に押し出すテーマに変更しました。

スライドの構成としてはこんな感じに変えています。

  • やり方がN個あるのでN個を薄く紹介する→一番使いやすいと思った物をちゃんと紹介
  • 余談的なネタを削除
  • YouTubeインパクトのあるサムネを出した方がいいと聞いたので最後におふざけを追加

結局15分の動画作成に合計1人日以上使って、なんだかんだで締め切り1日前に投稿できました。

得られた物&改善したいところ

自分の未熟さを痛感しました。もっと上手くできると思っていたけど、現実はそんなに甘くなかったなぁ、と。Testcontainers自体はシンプルで使いやすいライブラリですが、それを紹介するのは本当に難しい。JJUGに登壇する人のレベルの高さを改めて実感しました。

あと最後のライブセクションは緊張しすぎて、せっかくJJUGTシャツを着てたのにZOOMのカメラがオフになっていたという自爆をかましました!

それでも、発表を見て使ってくれる人が1人でもいれば成功なのではと今は思っています。

発表や動画についても、「こんなレベルでもいけるんだったら俺の方がうまくやれるぜ!JJUG_CCC_Fallに来てください、本当の発表をお見せしますよ!」って思って登壇する人が増えてくれればなぁと思います。

FAQとか

モジュールにないコンテナも使えるの?

使えます。DockerComposeモジュールがあるので、移行することもできます。

コンテナを使ったテストにかかる時間の話

PCの性能次第。超ハイスペックマシンだと気にならないけど、少し古いPCだとストレス溜まるかも。 それでもCPUの性能が向上してきているのでユニットテストに組み込んでも実用的なレベルになってきているのではと思います。

CIハマったところ

Docker-in-Dockerで困ったことはあまりないです。 privilegedが使えない環境でTestcontainersがこけるところにハマりました。

Custom configuration - Testcontainers

移行での採用

開発中のデータベースバージョンアップで使えました。 TastcontainersでDBのバージョン指定しているところを変更し、GitにPushするだけで開発者全員の環境がバージョンアップされるの本当にやばい。

その他

ハマりどころはTestcontainersではなく動くコンテナ側やプロダクトコード・テストコードの方が多いです。 Testcontainersを使って並列でテスト実行は簡単なのですが、テストクラスで問題が出て泣く泣く諦めるケースも・・・。

最後に

初登壇かつ動画作成も不慣れなところをサポートしていただいたJJUGのスタッフさんに感謝しかないです。

おまけ

動画作りは面白かった&ボイロを購入して使ってみたいので今回のスライドのボイロ版を作ろうと思います

セキュリティ対策メモ

セキュリティ設計どうすればいいんですか?って聞かれたので説明するためネタを用意するためのメモ。 元ネタはこの本の3章あたり。

攻撃者の分析

キルチェーンで考える。キルチェーンとは攻撃者がシステムに侵入して目標を達成するための具体的手順。

1. 対象選定

攻撃者は「誰の」「何を」目的とするのかを決定する。

  • SNS登録者のパスワード
  • 銀行口座の預金
2. 偵察

攻撃者が攻撃するシステムに対する情報を収集する。ハード・ソフトの双方から行う。

  • ハード:システム構成やセキュリティ対策
  • ソフト:組織体製図、ビジネス目標、採用情報、従業員や関係者
    3. 武器化

2の偵察で得た情報に基づいて攻撃方法の決定と攻撃準備を行う。 例えばマルウェアDoS攻撃用のサーバー、偽造した証明書などを用意する。

4. 配送

攻撃対象に用意した武器を用いて脅威を送り込む。 フィッシングメールの送信、SQLインジェクション水飲み場攻撃やWebサイトの進入。 攻撃経路を確保する。

5. 攻撃

経路を用いて潜入した攻撃対象のシステムに拠点を構築する。 例えばマルウェアを実行するための権限を取得する。

6. インストール

攻撃するためのコードをインストールする。 バックドアや認証情報の取得。

配送・攻撃と異なり、持続的な経路を確保する。 標的型攻撃でマルウェアを送り込む攻撃であれば、配送はメール送信、攻撃でマルウェア起動、インストールで対象のPCに潜伏になる。

7. コマンド&コントロール

インストールしたソフトウェアを用いて目的を実行するための準備。 例えば外部に通信するための帯域の確保や認証情報の取得等。

8. 目的実行

目標達成に向けた行動を実行する。 例えば一時的に監視をオフにしてその間に目標のファイルを盗む。 目標達成と同時に攻撃されていることが判明する場合が多い。 (例えば不正送金等)

防御者の観点

キルチェーンに対して、事前準備・特定・封じ込め・根絶・復旧・教訓からなるインシデント対応サイクル準備する。 それぞれのフェーズはキルチェーンの以下のフェーズに対応する。

  • 1〜3:事前準備
  • 4〜8:特定・封じ込め・根絶
  • インシデント後:復旧・教訓

このサイクルを回すことで攻撃に対抗する。

1. 事前準備

以下の準備を行う。

  • データ測定:システムの監視。そもそも攻撃を受けていても測定できなければ対策できない。
  • ハードニング:セキュリティパッチの適用、ファイアウォール等の攻撃を制限する
  • プロセスと文書化:インシデント発生時の対応準備。マニュアルやコミュニケーションルート
  • 訓練:インシデント発生時の訓練
2. 特定

リソースに対する攻撃を検知する。 例えばデータ測定で監視しているサーバーやユーザーが、異常な動作をしていることを検知する。

3. 封じ込め

攻撃を緩和する。 例えばネットワークをブロックしたり、不正行為を行っていると思われるアカウントのロック、感染したシステムを一時ダウンさせる。

このフェーズ以降はプロセスと文書化による手順や訓練が効果を発揮する。

4.根絶

攻撃者を完全に締め出すための対策。

  • パスワードが流出したのであれば全アカウントをリセット
  • 証明書や認証情報の再生成
5. 復旧

システムを元の状態に復旧する。 そのまま復旧しても再度攻撃を受けるため、必要な対策はここで行う。

6. 教訓

インシデントの振り返り。事前準備に繋がる。 例えばネットワーク構成の脆弱性を突かれたのであれば、1のハードニングでネットワーク構成を見直す。

で、何をすればいいのか?

まずは一般的なセキュリティ対策を行う。AWS上でSpringアプリを動かすのであれば以下のことを設定する。

  • 最小権限のIAMロールの設計やWAF・セキュリティグループ
  • JavaやSpringのセキュリティパッチの適用。脆弱性のスキャン。ゼロデイ対策。
  • XSSCSRFの対策
  • CloudWatchや監視SaaSを利用したログやメトリクスの取得と分析
  • 侵入テストの実施
  • コードレビュー

ここら辺はいい資料や書籍といった教科書がたくさんあるのでその通りにやればいいだけだと思う。 これができてれば、事前準備のデータ測定とハードニングはできているはず。

訓練は攻撃者が標的にしそうなところを中心に対策する。

  • ユーザーのログインIDとパスワード
  • お金を取り扱うサービスであればフィッシング
  • AWSルート権限のっとり

ここら辺の攻撃とかをシミュレーションしてセキュリティ対策を入れていけばいいと思います。

パスワードハッシュ化にbcrypt使う理由をまとめてみた

今日やってきたセキュリティ専門家があまりにも酷かったので書いた。書いた本人はアプリな人なので細かいところが違ったらごめんなさい。

敵「SHA-256の方がアルゴリズムとして優れている。CRYPTRECのリストにも乗っている。bcryptのblowfishは最新のリストから外れている」

確かにハッシュ化するアルゴリズムだけを比較したら、SHAの方が優れているかもしれない。ただ、攻撃者はハッシュアルゴリズムに対して攻撃は仕掛けてこない。攻撃者が狙うのはパスワード。あるかないかわからないアルゴリズム脆弱性を探すより、「P@ssw0rd」のような脆弱なパスワードや短いパスワードを見つける方が簡単である。

f:id:setys:20200402232300p:plain

じゃあアルゴリズムの目的は何かというと、平文のパスワードからハッシュを生成するのに負荷を発生させて時間をかかるようにすること。そうすれば、その間にサービス運用側は流出に対処することができる。全ユーザーのパスワードをリセットして再設定するような対策が考えられる。

ハッシュ生成に負荷をかけるという観点からすると、bcryptは故意にCPUに負荷をかけるように設計されている。Argon2ならメモリにも負荷をかける。それに対しSHAはそういう設計になっていない。

SHAの場合、対象文字列の長さによって処理の時間が変わるという問題がある。詳細は以下のページを参照。

pthree.org

敵「AESで暗号化する方式もある。AESもCRYPTRECで推奨されていて安全だ」

暗号化をした場合、鍵と暗号文が流出した時点で全てのパスワードが複合できてしまう。守らないといけない物が2倍になる。ログインのような頻繁に暗号・複合が行われる処理の場合、鍵を安全に保管するのにも気を遣う。

暗号化の問題は、何よりも複合して元の平文が入手できてしまうこと。内部不正や脆弱性に大して完璧な対策が要求される。鍵を絶対安全とも言えるHSMに格納したとしても、HSM*1にアクセスできれば複合できてしまう。bcryptなら内部の人間であろうと複合はできない。

個人的な経験だけど、AESでパスワードを暗号化しているシステムは、パスワードなり暗証番号を参照するという要件がある。窓口オペレーターがパスワードを忘れた人に口頭で伝えたりする。パスワード紛失時はリセット→再設定に倒すべきだけど、そういう客に限って大体嫌がることがほとんどで辛い・・・。

敵「独自アルゴリズムを採用することも検討・・・」

優秀な数学者や暗号の専門家を雇い、数年かけて完璧なアルゴリズムを開発する金と時間とbcryptを今すぐ採用することを天秤にかけてください。

そもそも目的は完璧に破られないことではなく、流出してから対策までの時間稼ぎで。

敵「じゃあどうすればいいんですか?」

  • 長くて安全なパスワードを入力できるようにする
  • bcrypt(またはargon2)を採用する
  • MFAを義務付ける

セキュリティに関しては、余計なことを考えずにグローバルスタンダードな権威に従っておけばいい。なんで「bcryptを使うんだろう?」って疑問に思ったら、調べればいいのです。調べれば専門の人がもっと正確に書いているものはたくさん見つかるはず・・・。

追記

あとは自分で作らないことも重要。Spring Securityとかのフレームワークを正しく使う。

*1:そもそもHSMは鍵を守るものである。暗号化対象であるパスワードは守ってくれない。HSMに金をかけるくらいならbcrypt使う方が1000倍マシで安全。

Spring Fest 2019メモその2 Reactive Spring

Josh LongさんがライブコーディングをしつつReactiveについて3時間弱熱く語ってくれるセッション。
すごく勉強になった。

リアクティブプログラミングは、より多くのユーザーリクエストを処理するための水平スケール依も効率がいい解決手段。
CPUに効率よく仕事をさせることができる。

これまでのプログラミングではCPUがIO待ちによるアイドリング状態が多い。
IO待ちの間、CPUは何も仕事をしていない。

リクエストを受け付けるため、大量のスレッドが待機状態にする必要がある(IO待ち)。
大量のリクエストを受付けるためにスレッドを増やすと、スレッド管理のためにOS、CPUに無駄な仕事が発生する。

それに対してリアクティブプログラミングはスレッドを効率よく使う。
データが発生するとコールバックで処理を行うため、スレッドをキープし続ける必要はない。

Javaの非同期のIOはJava 1.4でNIOによって実現可能。
18年前に出ているが、APIが使いにくいため使われていなかった。
また、無理に使わなくてもロードバランサーでどうにかできた。(非同期IOに比べれば効率は悪いが・・・)

リアクティブは4つのシンプルなインターフェースの構成。
Subscriber、Publisher、Processor、Subscription

Reactiveに対応したデータソースは、CosmosDB、GoogleのFirebase、Elasticsearchとか様々ある。
RDBSQL使いたい人のためにR2DBCを提供。
R2DBCはGAだが、SpringBootとのインテグレーションはまだ。

ポーリングはユーザーエクスペリエンスがよくない。
特に市場の株価のようなライブの情報が必要となる場合。
リアルタイムの通信が必要な場合、1ソケット1スレッドは効率悪い。
ユーザーが明示的にシャットダウンをしないとスレッドのロスも発生する。

Reactiveの背後にはスケジューラー(のようなもの)がいる
必要なスレッドはCPUのコアだけ。(デフォルト設定)
処理を書く際はブロッキングをしてはいけない
例えば4つのコアがあるときにブロッキングが発生すると、処理性能が25%停止する
ブロッキングしなければいけない場合、ソースで明示的にしなければいけない。

ブロッキングされている処理の検出はBlockHoundで可能

github.com

Reactiveの利点はユーザーの数を2倍にしつつデータセンターのコストをそのままにすること。
新しいプログラミングモデルを提供してくれる。
従来であればリクエストに対して成功・失敗のどちらかを返していたが、リアクティブではいろいろな応答を何回も返せる。

リクエスト数の上限を設定する場合、ノード単位の指定は避ける。
なぜなら、スケールするとその分増えてしまう。
細かい単位での指定が必要。
例えばセール実施中の国は優先度を高くする。
寝ている時間の国の優先度を下げる

認証処理ではbCryptを使うが、これは時間がかかりブロックが発生する。
ReactiveのSpringSecurityはこの処理を別スレッドで行う。

リアクティブの世界の場合、リクエストを受け付けたスレッドと応答を返すスレッドが異なる場合がある。
受け付けたリクエストに対する処理がどのスレッドで行われているかは分からない。
しかし、リクエストではSecurityの情報が必要になる。
スレッドローカルは利用できないため、サブスクライブした処理の中でどこからでも参照できるSubscriberContextを利用する。

サービスは落ちることがある。
綺麗な形で落とし、外から見たら何も起こらなかったようにみせる。
ダウンしているのが分かっていれば、そのサービスを呼ぶ必要はない。
サーキットブレーカーを利用する。

サービスが10インスタンス立ち上がっていることがわかっていれば、どこのサービスを使えるかがわかる。
1つのサービスがダメでも他のところに送ればいいが、リトライ・タイムアウトのハンドリングが難しい。
なので最初からリクエストを全てのサービスに送るヘッジングという手法がある。
リクエストから同じ結果が帰ってくる場合に有効。
最初に応答が返ってきた物を有効にし、他のストリームはキャンセルする。

双方向の通信をするため、いろいろな仕組みがある。
gRPCはプロトコルバッファーという縛りがある。それに対応したコードは書きたくない。
websocketはセキュリティの問題がある。
さらにペイロードがテキストで多様なデータが飛び交うと難しい。

RsocketとActuatorを組み合わせることで、送信先インスタンスがビジーであれば他のインスタンスにリクエストを送る仕組みがある。
RsocketとSpringSecurityを組み合わせられるため、セキュリティの担保もできる。
ゲートウェイ経由でバックエンドのサービスと直接接続できる。
RSocketならポインタが残るため通信が切断されてもレジュームできる。
クライアントが多くなるほど、他の方式と比較してコストの効率がよくなる。

Spring Fest 2019メモその1 キーノート

Spring One 2019

youtubeにセッションがあり視聴可能

2つの新しい機能を発表
RSocketとR2DBC

Pivotal Spring Rutimeの発表
Java、Spring、Tomcat等をセットでサポート

Springboot2.2の変更点

Java13をサポート
今後、Javaのバージョンの対応はSpringBootのアップデートで対応
(Java14の対応は2.2で行うのではなくSpringboot2.3になる?)

DependencyManegementを更新
最も重要な機能はバナーが256色に対応したこと

Rsocketの追加
Facebookも使用している

Imutable Congfiguration Propertie
一定間隔でコンフィグを再読み込み?

JUnit5

テストメソッドがpublicじゃなくてもよくなる temp directoryとかのテストに必要な便利な機能
SpringBootTestだけで良くなる
RunWithアノテーションが不要になる

パフォーマンス

  • 起動時間の改善:GCの回数削減、メモリフットプリントを小さくなったため
  • 遅延初期化:Beanは要求されなければ作成されない
  • ランタイムのパフォーマンス改善

Graalvmサポート

GraalVMは多言語対応でネイティブイメージを生成可能
ネイティブイメージは起動速度とメモリが圧倒的に少なくなるためサーバレスに向く。
しかし、スループットは下がり、リフレクションや動的プロキシに制約がある

Springは5.2でCGLIBを使わないモードが追加され、大体ネイティブ化できるようになった。
5.3では特に追加しなくてもネイティブ化を可能にする。

SpringCloudのアップデート

アルファベット順でロンドンの駅名を利用
Hoxtonが最新

Spring Cloud Netflixがメンテナンスモードになった。
今後の機能追加はなく、致命的な問題やセキュリティのFixのみ
代替手段は提供されているので公式ドキュメントを参照

Azure Spring Cloud

MicrosoftとPivotalの提携。

CloudNativeBuildpack

ソースコードからOCI標準のコンテナイメージを作成
Dockerファイルは不要
kpackを利用すれば、ビルドしてk8sにデプロイが可能

SpringBoot5.3

JDK17に向けた準備
GraalVMのネイティブイメージサポート
Rsocket、Corutinesの改善

Springboot 2.3

2020/4にリリース予定
コンテナ、k8sサポートの強化
依存ライブラリアップデート(SpringData)
2.3からリリース周期が6ヶ月周期に変更になる(今までは1年周期)

Springのサポート

1.XはすでにEoL
2020年1月に5.0と4.3の最後のリリース
2020/11 SpringBoot2.1 EoL
2020/12 Spring FW5.2 EoL

LINE DeveloperDayで聞いたセキュリティの話メモ

LIFFとかはきっと他の人がブログ書くだろうから地味(?)なとこを・・・。

FIDO

FIDOはセキュアなだけではなく、UXもいい。 LINEはFIDO ユニバーサルサーバーの認定を世界で初めて取得している。 LINEではFIDOを様々なサービスに導入していて、将来的にはパスワードを廃止することを目指している。

Auth0の人のセッション

企業がセキュリティのどこに投資したいかというアンケートでは認証、アイデンティティマネージャーという回答が高い。 でも実際はネットワークセキュリティ、ファイヤウォールに投資している企業がほとんど。 なぜそこに投資しないのか?

90年代は会社のプライベートな情報を保護するため、DMZ、FWに投資。

2000年代にはSaaSクラウドアプリが登場し、自宅からの接続というケースが発生。 企業はプライベートなセキュリティを拡張するために投資。 VPN、プロキシ、暗号化、ネットワークセキュリティ等々。

2010年代になると、identity providerにより複数のアプリにSSO。 覚えるパスワードの数が減りUXはよくなった。 しかし、企業はエンドポイントセキュリティやVPNに投資を続ける。理由は不明。 また、この頃からアイデンティティに対する侵害が多く発生。

informationisbeautiful.net

日本でもPSNの流出事件とか発生。

企業はようやく多要素認証に投資する。 多要素認証によりセキュリティは強化されたがUXは低下。 企業の利益はUXとデータがもたらすため、セキュリティの投資によりUXが下がると利益も下がる。

ゼロトラストに基づく連続的認証という考え方。 これまでは一度認証したらそのセッションは永続する。 そうではなく、confidentialレベルという数値で管理する。

confidentialレベルは認証した直後が最も高い。 この数値は以下のような場合に下がっていく。

  • 認証してからの時間経過
  • アクセスした地理が普段と異なる
  • キーボードの入力がいつもと違う

これに行おうとしているアクションごとに必要な数値を比較する。 例えば、高額の振り込みを行うのであれば、本人確認を再度要求してconfidentialレベルの数値を高くする。 少額の振り込みであれば、必要な数値は低くなる。 このように、アクションするときはconfidentialの現在の値と必要な数値を比較し、不足しているのであればconfidentialレベルをあげるために認証を要求する。

ゼロトラストはちゃんと勉強しないとダメっぽい・・・。