# 2021/02/14 メンター相談 [元URL](https://hackmd.io/@HideoKaizuka/S1sAM-8Z_) 質問 --- ### [普段サービス設計を行う際のセキュリティへの考え方](https://airtable.com/tblA4yYGHwaqDYKwx/viwAUwNVsR9rOkW6u/rec4UqSIGRR76U5Wf) 質問全文 > 普段サービス設計を行う際のセキュリティへの考え方を知りたいです。 > > Webサービスを設計する際に、課題8で登場したしたXSSやSQLインジェクション、その他の脆弱性に関して、どのような観点からセキュリティの要件定義や設計分析を行ったりしているのでしょうか > > ## 参考情報 > > 質問者の会社だとセキュリティを担当する別のグループがあり、私自身はセキュリティをあまり意識したことがなかったので、他の皆さんがどのように意識しているのか気になりました > > 他のメンバーの意見では、セキュリティチームが無く(最近作られそう?) ほとんど実装者の意識ととフレームワークの恩恵に頼っている形になっているそうです。 > (https://railsguides.jp/security.html) 解答 - リクルートにいた頃にはセキュリティのチームがいた。 - フレームワークやライブラリから逸脱する時に考える。容易に逸脱しない。 - Reactだったら[dangerouslysetinnerhtml](https://ja.reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml) を使う時に注意する。 - バックエンドでは基本はORマッパーを使うので、あまり気にしない。ORマッパーで作れないSQLを考える時に注意する。 - フロントエンドチェックリスト[FrontEndCheckList](https://github.com/thedaviddias/Front-End-Checklist) - フレームワークから逸脱する時だけ、実装の確認や逸脱した時の影響を理解しておくことが多かった。 - MozilaObservatory https://observatory.mozilla.org/ - MozilaObservatoryは高いスコア出すの難しい(プラハさんのサービス:D Twitter:B) ### [セキュリティ診断などをどのように行っているのでしょうか ](https://airtable.com/tblA4yYGHwaqDYKwx/viwAUwNVsR9rOkW6u/recuV5tjgV1JNGaXd) 質問全文 > セキュリティ診断などをどのように行っているのでしょうか > > セキュリティ診断を行う際に使用している診断ツールや、どのタイミングで使用しているのかなど参考例を聞きたいです > > ## 参考情報 > > 下川は今回の課題を解く際に https://securityheaders.com/ でセキュリティに関するヘッダの対応具合などを見てたりしてました(実務では使っていないです...) > > 他のメンバーの意見では、brakemanと言われるRubyの脆弱性監視ライブラリをRailsアプリケーションに組み込んで、日常的に監視していたりするそうです!(具体的には、コードをGithubにpushした際にCircleCIが動かすJobの中でbrakemanを組みこんでいるようです) 解答 - フロントエンドなら[FrontEndCheckList](https://github.com/thedaviddias/Front-End-Checklist)を使って確認することが多い。 - MozilaObservatory https://observatory.mozilla.org/ - デプロイする前にやる - breakman→リクルートでもやってなかった ### [業界特有のセキュリティに関する意識や対策の違いを知りたいです](https://airtable.com/tblA4yYGHwaqDYKwx/viwAUwNVsR9rOkW6u/recrH4ZYJtWNF0opq) 質問全文 > 業界特有のセキュリティに関する意識や対策の違いを知りたいです > > 業界ごとにどういった観点からセキュリティリスクを考えているのか聞いてみたいです > > ## 参考情報 > > 質問者の場合はインターネットに公開しないB2Bサービス担当なので、あまりセキュリティを意識したことがないです(別のグループがやっているというのもありますが...) > > 他にも金融系だとセキュリティ対策が厳しそうというのもありました 解答 - 業界特有の対策はあまりない。 - 金融系は部屋が別れていた。物理的に入れない。 - リクルートのサーバ部屋には目の認証、USB持ち込まれないかとか、部屋に入る時も警備員にチェックされるとか。 - どのアプリ作る時もObservatory - リクルートはDBの個人情報全てハッシュ化してる あまり生でDBに入れてない - 個人情報を40万人分誤って送ってしまった大事故があっていらい厳しくなった - 人事系のサービスは金融サービス並にセキュリティが厳しい。(個人情報を大量に扱うため。) ### [バックエンドとフロントエンドでのセキュリティ対策の違いを知りたいです](https://airtable.com/tblA4yYGHwaqDYKwx/viwAUwNVsR9rOkW6u/recZP7EcZlVT47JI6) 質問全文 > バックエンドとフロントエンドでのセキュリティ対策の違いを知りたいです > > フロントエンドにReact、バックエンドにNodejsを採用した際に、脆弱性への攻撃に対してバックエンドではCSRFトークンの発行などの対策は必須かと思いますが、フロントエンドではどういった対策を施すことがあるのでしょうか > > ## 参考情報 > > 調査した感じだと、例えばReactの場合だとデータバインディングを使用すれば自動的にインジェクション対策を行ってくれているそうです。(https://reactjs.org/docs/introducing-jsx.html#jsx-prevents-injection-attacks) > > またReactでは innerHTMLの代わりに dangerouslySetInnerHTML を使うようにもなっていて、XSSの危険があることをかなり丁寧に知らせてくれるそうです 解答 - フロントエンドなら[FrontEndCheckList](https://github.com/thedaviddias/Front-End-Checklist)を使って確認することが多い。 - バックエンドはDBの読み込みや書き込み周りを注意するべき。ORマッパーを使っていれば、それほど気にしない。 - フロントエンドの不具合でXSSが出ることがあった。 - JWTの脆弱性が昔あったくらい。アプリの書き方が悪いよりも使っていたツールの脆弱性。 - 競合他社のクローリングを弾くとか。 - いたずら防止とか。 - アメリカのスタートアップでそういうのを検知するサービスがあった。 - Rubyのメタプロでこういう脆弱性があるとかはある。 - JSではない? - メタプロ怖い ### [デプロイ時のキャッシュ対策(デプロイしたけどキャッシュのせいで反映されないことに対する対策)](https://airtable.com/tblA4yYGHwaqDYKwx/viwAUwNVsR9rOkW6u/recGaQn3d3jWHabDM) > デプロイ時のキャッシュ対策(デプロイしたけどキャッシュのせいで反映されないことに対する対策)について。 > 2つお伺いしたいです。 > 1.NextやNuxtではビルドされたタイミングで更新があればcssやjsのファイル名(ハッシュ値ついてる)が変わるという対策がなされているかと思うのですが、そのcssやjsを呼び出す元のファイルがキャッシュされて、結果的に変更が反映されないということが起こらないのにはどんな対策がされているのでしょうか?実行してみた感じETagが使われていそうですが、その辺りもフレームワークがいい感じにやってくれているのでしょうか? > 2.デプロイ時にやるべきキャッシュ対策は何かあるでしょうか? > 余談ですが、1年くらい前に勤めていた会社ではphpでフレームワークなしの現場だったのですが、 > <src="main.js?date=<php? echo filemtime(main.js);>"> > のようにファイルが更新された日時をクエリに入れてました。 解答 - キャッシュが残ることはある。 - ブログとか静的HTMLはキャッシュさせないという対策をする。 - NextjsだとETagを切る設定ができるhttps://nextjs.org/docs/api-reference/next.config.js/disabling-etag-generation - ETagを切った方がいいものもある。 - ETagはくせもので自分でつけることはあまりない。 キャッシュ対策について - cssやjsだと中身のハッシュ値で変えるかクエリパラメータなどで更新する。 - ExpressのETagをどうやって作っているか - res.send()で渡すbodyのハッシュ値 - ETagに時間値に設定すると複数サーバ使っている時に問題になる。 - コンテンツからハッシュを作る方がいい。 ### [If-Modified-Since と If-None-Matchの使い分けについて](https://airtable.com/tblA4yYGHwaqDYKwx/viwAUwNVsR9rOkW6u/receI5SlC4vqoJ5iy) > If-Modified-Since と If-None-Matchの使い分けについて。 > pair-1bの考えとしては「コンテンツの更新の判断を正確、厳密に行いたい、もしくはサーバーに時間を設定する機能が無い場合はIf-None-Matchを使用する」という使い分けかと考えていました。他にどんな使い分けがあるでしょうか? > また、下記の記事を見ると、複数台サーバがあるときはETagに扱いには注意が必要なようですが、複数台構成の場合はETagは付与しない方がいいのでしょうか? > https://blog.redbox.ne.jp/http-header-tuning.html 解答 - 基本はIf-Modified-Sinceを使う。 - シンプルなので。 - 両方指定することが多い。 - ETagはあまり使わない方がいい。 - 静的なコンテンツの場合はどちらでもいい。 - 1つ前の質問のようにETagの設定値によっては複数サーバ使っている時に問題になる。 - 古いキャッシュを強制的に消す時に、クエリにキャッシュバスティングを設定することはある。 ### [エラーメッセージの内容までテストすべきなのでしょうか?](https://airtable.com/tblA4yYGHwaqDYKwx/viwAUwNVsR9rOkW6u/recS1qz69u70hhjiS) > エラーメッセージの内容までテストすべきなのでしょうか? > > 今回のような小規模な関数では必要ないと考えて、そこまでのテストは行いませんでした。 > ペア内では、大きなプロジェクト等で独自に定義したエラーメッセージを出している場合、想定するエラーメッセージがでているか確認する目的でエラーメッセージの内容をテストするのかな?と考えました。 > > [課題10 jestで単体テストを書こう] > > --- > チーム内では、以下のような意見をいただきました。 > > - 自分がAPI開発する際は、フロントにエラー文言を返す時はエラーのメッセージも合っているかをちゃんとテストすることが多い > - エラーメッセージが間違っているとバグ修正などの際に原因特定で余計な時間をとられることもある気がします。。 > - バッチログのメッセージをもとに業務対応を行うため、少なくとも独自に設定しているメッセージは全てテスト対象だった > > エラーそのものだけでなく、エラーメッセージも重要な場面が多いため、他のテスト同様、影響がある、よく呼び出される場所ではテストした方が良さそうだな、と思いました! 解答 - 実務ではテストすることが多い。 - メッセージ内容までテストする方がいい。 - カスタムエラーを定義してる場合は、タイプのみをチェックするでもいい。 ### [TypeScriptの型エラーで検出できる場合でも、テストをした方がいいのでしょうか?](https://airtable.com/tblA4yYGHwaqDYKwx/viwAUwNVsR9rOkW6u/recNJMC5So9d8Batn) > TypeScriptの型エラーで検出できる場合でも、テストをした方がいいのでしょうか? > > 「課題:jestで単体テストを書こう」 > 課題にて、テストのパターンとして 「例:string型の配列を渡したら...?(ビルド時に例外が発生するため、そもそもテストが動かないはずです)」 とありました。 > > ビルド時の型エラーを無視する設定にして、 sumOfArray(["1", "1"]) のテストを実行してみると、単に文字列結合された "11" が返ってきます。 > > そのため、typeof 等で 型を検証し、number型以外の場合に Error を throw するという実装を sumOfArray() に追加し、文字列の配列が渡された時はthrowErrorされることをテストしました。 > > 修正した実装: https://github.com/sushidesu/praha-challenge-templates/blob/4f60e7e886d1decc8f3cf654d968e7d46cb7dc87/jestSample/functions.ts#L6 > テスト: https://github.com/sushidesu/praha-challenge-templates/blob/4f60e7e886d1decc8f3cf654d968e7d46cb7dc87/jestSample/__tests__/functions.test.ts#L27 > > こちらは課題の意図に合っているでしょうか? > > また、 型で検出できるものであっても、typeof 等を使用して二重に検証する必要があるのでしょうか? > 同様に、型エラーで検出できる場合でも、テストをするべきなのでしょうか? > > --- > ほかのメンバーからは以下のような意見をいただきました。 > > - 課題一覧の並び的に「ビルド出来ないこと」もテストする? > - 自分は、「string型の配列を渡したら...?」のテストは要らない派 > - 型安全に開発するためにTypeScriptを用いているはずなので、型で検出できるものまでテストしてしまうとTypeScriptを使用している意味がなくなってしまう 解答 - 型エラーがある場合は、そもそもテストが実行できない。 - 型エラーはビルド時、テストはランタイム時に防ぐ。 - any型の時はテストした方がいいかも。 - TypeScriptのテストでは、基本的にはビルド時に確認出来ないことをテストするべき。 ### [DIする対象について](https://airtable.com/tblA4yYGHwaqDYKwx/viwAUwNVsR9rOkW6u/recsSzWdCcvq8ANwn) > DIする対象について > NameApiService等を注入する際に、自分は以下のようにメソッドを渡す形に修正しました。 > > - https://github.com/sushidesu/praha-challenge-templates/blob/4f60e7e886d1decc8f3cf654d968e7d46cb7dc87/jestSample/functions.ts#L19 > - https://github.com/sushidesu/praha-challenge-templates/blob/4f60e7e886d1decc8f3cf654d968e7d46cb7dc87/jestSample/functions.ts#L33 > > 必要なものだけ渡すことで影響範囲が狭いことを明示したかった、という意図があります。 > > インスタンスをそのまま渡すのとどちらが良いでしょうか?両者のメリット・デメリットも知りたいです。 > > --- > チーム内では以下のような意見をいただきました! > > - 「依存性の注入 = 依存オブジェクトの注入」という解釈だったので、インスタンスを渡すようにした > - インスタンスを直接渡した方が後々コードが肥大化した際にコードを追いやすくなる? > - 関数だけを渡すと、どこの関数なのかぱっと見分からなくなる?(TypeScriptだとそこは問題ない?) 解答 - コンストラクタで渡すかメソッドに渡すかは好みの部分が大きいが、関数を毎回渡すと、リポジトリ(今回の課題だとクラス)の情報が散らばってしまう。 - 毎回関数の情報までを知らないといけなくなるため、インスタンスを渡すことが多い。 - コントローラー層で全ての依存関係を注入することをよくやる。 - クラスの場合は、コンストラクタでやる。 - 今回の課題の場合は関数なので変わる。 - 基本的には関数単体ではなく、クラスに関数をまとめて、コンストラクタに依存関係のインスタンスを追加して使用することが多い。 - メソッドにDIする場合は、モジュールごと渡す?メソッドだけ渡す?(データベース関連のクラスの場合は、saveだけじゃなくて、connectionが必要な場合もある。) ### [spyOn() jest.fn() jest.mock() の使い分けについて](https://airtable.com/tblA4yYGHwaqDYKwx/viwAUwNVsR9rOkW6u/reclgTMTIBQ2KpIVl) > spyOn() jest.fn() jest.mock() の使い分けについて > ペア内で話し合ったところ、 > > - 基本 jest.fn() を使って モックを作る > - spyOn は元の動作を維持したい等特殊な場合に使う > - spyOn は .mockImplementation 等しない限り元の動作を維持する > - 上書きしても、mockRestoreで元の実装に戻せる > - jest.mock() は 外部モジュールをモックしたい時に使う > > という認識になりましたが、どう思いますか? > > またチームのメンバーから、「jest.mockですべてモック化するとすべてのインスタンスに影響してしまう(*)ので、予期しない挙動に繋がる」という意見をいただきました。jest.mock() はあまり使用せず、なるべく jest.fn() でモックするようにした方がいいのでしょうか? > > * (mockを定義したスコープにもよるが) > --- > チームのメンバーからも大体同じイメージだと意見をいただきました。 > > - jest.fn() -> シンプルに関数をモック化したい時に使う。(基本的にはこれ) > - spyOn -> 特定のオブジェクトに対して、モック化した関数を追加したり、mockRestoreを使用してオリジナルな関数に戻したい時に使う。 > - jest.mock() クラス全体をモック化したい時に使う。(全てをモック化してしまうと、予期しない挙動に繋がるので、jest.fn()どうしてもモックを挟めない時だけ使う。) 解答 - spyOnは元々のメソッドを使うことが出来るため、統合テストに使うことが多い。 - データベースに保存処理を行うテストをする際に、保存関数がちゃんと実行されて、データが保存されたかどうかを確認したい時に使う。 - jest.Mockは元々のメソッドが消える。(Mockの関数に置き換わる) - 単体テストに使うことが多い。 - jest.fnは関数だったらjest.fnでクラスだったらjest.Mockを使う。 - jestMockの影響範囲はファイル内に止まるため、スコープを意識していれば問題なく使って良い。 - 単体は書くけど統合テストはあまり書かない。 ### [DIの引数の順番](https://airtable.com/tblA4yYGHwaqDYKwx/viwAUwNVsR9rOkW6u/recoLRv6gPijshasX) > DIするときの引数の順番について > > ① getFirstNameThrowIfLong(maxNameLength: number, nameApiService: NameApiService) (DIが後) > ② getFirstNameThrowIfLong(nameApiService: NameApiService, maxNameLength: number) (DIが先) > > どちらの方がいいでしょうか? 解答 - DIを先に渡す。 - 絶対に必要な引数から渡す。 - 可変長引数があると、引数の最後に可変長引数を設定する必要があるため。 ### [eslintのルールは何を設定していますか?](https://airtable.com/tblA4yYGHwaqDYKwx/viwAUwNVsR9rOkW6u/rec01Im7xGUPk0lz0) > eslintのルールは何を設定していますか? > eslintrc の extendsにて airbnb や google ではなく eslint:recommended を採用している理由はありますか? > > > 派生して、新規のプロジェクトを作る際に、eslintrc や prettierrc、 tsconfig はどのように作りますか? > > - 既存のプロジェクトからコピペしてくる > - 何かツールを使う > > 自分は過去のプロジェクトからコピペが多いです。何かいい方法があれば知りたいです。 解答 - eslint:recommendedにこだわりはない。 - 普段はairbnbを使うことが多い。 - 何かルールがあることが重要でプロジェクト事でいい。 - prettierも既存の設定をコピペすることが多い。 - tsconfigも最初に作って終わり。これはしてるみたいな設定はあるか?_ - strict true - typeORM使う時はDecorator関連の設定 - ルートディレクトリは/srcにする - pathで@でエイリアス - airbnbにしてる理由は流行りでw - イケてるプロジェクトはairbnbが多かった - ルールは厳しめかも。 ### [throwかthrow.error](https://airtable.com/tblA4yYGHwaqDYKwx/viwAUwNVsR9rOkW6u/recEspNZHZZPrttLL) > エラーになることを確認するテストは、expect().throw() と expect().throwError() どちらを使うのが良いでしょうか? > aliasなので動作に違いはなさそうです。より分かりやすいのは throwError() のほうでしょうか? 解答 - throwを使うことが多い。短いから。 - async awaitか expect〜だとacync awaitを使う。 その他 --- ### 依存性の注入とmockについて - jest.mockをデータベースmock自体をjestmockで使えば、テストカバレッジを100%にできるんじゃないか? - 依存性の注入の方が、テストライブラリの性能によらずにできる。 - DHHはテストのために依存性の注入をするのはおかしいと思っている。 - 設計をきれいにするために依存性の注入を使う。脱着がしやすいところが依存性の注入。 - 言語の思想によって変わるが、TypeScript自体が軽量な言語なので、なるべく依存関係を持たせない実装を行いたい。 ### 外部のライブラリをmockする - axiosやnodefetchなど。テストする時には、設定や型がないと怒られるが、全部定義する必要あるか? - 型を推論してくれる関数があるので、それを使う。自分でマニュアルで定義することもある。 - あまりそういう状況がないので、書き方かもしれない。ここはあとでソース見てくれるっぽい。 ###### tags: `メンター相談`