コマンドの終了ステータスあれこれ

bash: GNU Bourne-Again Shell

パイプで連結したコマンド文字列の終了ステータス

  • パイプで連結したコマンド文字列の終了ステータスは、最後に実行したコマンドの終了ステータスになる
  • パイプで連結したそれぞれの終了ステータスが知りたいときは予約変数の PIPESTATUS 配列を参照する
    • (配列の添え字は 0 から数える)
      • 1 番目なら ${PIPESTATUS[0]}
      • 2 番目なら ${PIPESTATUS[1]}
      • 3 番目なら ${PIPESTATUS[2]}
    • $? と同じく、次のコマンドを実行すると内容が消える
$ ls -l log.txt
ls: cannot access 'log.txt': No such file or directory
$ foo | tee log.txt
bash: foo: command not found
$ echo $?
0
$ ls -l log.txt
-rw-r--r-- 1 y.okazawa 1049089 0  8月  7 19:07 log.txt
$ foo | tee log.txt
bash: foo: command not found
$ echo ${PIPESTATUS[@]}
127 0

log.txt は存在しない。
foo は存在しないコマンドだからすぐに消えた。
foo を実行したプロセスの標準出力は空だから tee コマンドは何も受け取ることなく log.txt を作成するだけで終わる。
tee は正常終了したので終了ステータス $? は 0 になった。
ファイルサイズ 0 の log.txt が存在する。
PIPESTATUS は長さ 2 の配列変数で、foo の失敗による終了ステータス 127 と tee の成功による終了ステータス 0 が入ってる。
$ ls -l log.txt
ls: cannot access 'log.txt': No such file or directory
$ echo 'start' | foo | tee log.txt
bash: foo: command not found
$ echo $?
0
$ ls -l log.txt
-rw-r--r-- 1 y.okazawa 1049089 0  8月  7 19:07 log.txt
$ echo 'start' | foo | tee log.txt
$ echo ${PIPESTATUS[@]}
0 127 0

log.txt は存在しない。
echo コマンドの標準出力は foo に接続されるはずだけど foo はすぐに消えた。
foo を実行したプロセスの標準出力は空だから tee コマンドは何も受け取ることなく log.txt を作成するだけで終わる。
tee は正常終了したので終了ステータス $? は 0 になった。
ファイルサイズ 0 の log.txt が存在する。
PIPESTATUS は長さ 3 の配列変数で、echo の成功による 0 と foo の失敗による 127 と tee の成功による 0 が入ってる。
$ ls -l log.txt
ls: cannot access 'log.txt': No such file or directory
$ echo 'start' | tee log.txt | foo
bash: foo: command not found
$ echo $?
127
$ ls -l log.txt
-rw-r--r-- 1 y.okazawa 1049089 6  8月  7 19:12 log.txt
$ echo 'start' | tee log.txt | foo
$ echo ${PIPESTATUS[@]}
0 0 127

log.txt は存在しない。
echo コマンドの標準出力は tee コマンドの標準入力へ接続し、log.txt と標準出力へ書き込まれる。
tee コマンドの標準出力は foo に接続されるはずだけどfoo はすぐに消えた。
foo は存在しないコマンドだったので終了ステータス $? は 127 になった。
ファイルサイズ 6 byte (s t a r t \n) の log.txt が存在する。
PIPESTATUS は長さ 3 の配列変数で、echo の成功による 0 と tee の成功による 0 と foo の失敗による 127 が入ってる。

xargs の終了ステータス

xargs(1)

Exit Status

xargs exits with the following status:

0 if it succeeds 123 if any invocation of the command exited with status 1-125 124 if the command exited with status 255 125 if the command is killed by a signal 126 if the command cannot be run 127 if the command is not found 1 if some other error occurred.

Exit codes greater than 128 are used by the shell to indicate that a program died due to a fatal signal.

  • 全部成功したら xargs の終了ステータスは 0
  • 終了ステータスが 1 から 125 のコマンドが 1 つでもあるなら xargs の終了ステータスは 123
  • 終了ステータスが 255 のコマンドが 1 つでもあるなら xargs の終了ステータスは 124
  • いずれかのコマンドがシグナルで停止したら xargs の終了ステータスは 125
  • いずれかのコマンドを実行できなかったら xargs の終了ステータスは 126
  • いずれかのコマンドが存在しなかったら xargs の終了ステータスは 127
  • それ以外の何かがあったら xargs の終了ステータスは 1

128 以上の終了ステータスはプログラムが致命的なシグナルにより停止したことを伝えるためシェルが使う。

コンテナやサーバー、アプリケーションの依存ライブラリの脆弱性を Trivy でチェックする

情報

準備

基本的な使い方は README を読めばすべて解決する理想的なツールです。

いろいろあるけど、インストールスクリプトを使う方法が一番楽だと思います。

curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/master/contrib/install.sh | sh -s -- -b /usr/local/bin
command -v trivy
/usr/local/bin/trivy

Go 処理系が入っているなら go get でもいける。

go get -u github.com/aquasecurity/trivy/cmd/trivy
command -v trivy
/home/y.okazawa/.go/bin/trivy

今のところ Windows の Git Bash ではちゃんと動かないみたいなので、WSL で操作するといいでしょう。

使用例

コンテナイメージをスキャンする

コンテナイメージのファイルシステムをスキャンするだけで特別な違いはなさそうです。 実行中のコンテナをスキャンしたいときは docker save で保存した tar ファイルを指定する。

trivy image name:tag
trivy image --input image.tar

ファイルシステムをスキャンする

Docker コンテナをビルドするときはこちらの使い方をするといいみたい。

trivy fs path/to/source

共通するオプション

  • 発見したい脆弱性の種類を指定する
    • --vuln-type
    • os あるいは library をカンマ区切りで並べる
    • 初期値は os,library
  • 脆弱性の有無に関わらずスキャンしたパッケージを表示する
    • --list-all-pkgs
    • 前回の結果と比較すればパッケージの増減を検出できるな
  • 出力する深刻度(severity)を指定する
    • --severity
    • 初期値は UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL

スキャンした結果の出力形式

JSON 形式。jq とかで必要な情報を抽出する感じになりそう。

trivy image --format json name:tag

テンプレートで Go template 直書き。いい感じにログ出力するとかそういう用途にいいのかな。

trivy image --format template --template '{{ range . }} {{ .Target }} {{ end }}' name:tag

テンプレートで Go template で記述した外部ファイルを指定。これは JUnit XML 形式の場合。

Jenkins や Bamboo などの CI サーバーなら JUnit XML 形式をいい感じに処理できるのでお勧め ユニットテスト結合テストの結果と同じように扱える

curl -fsSL --remote-name https://raw.githubusercontent.com/aquasecurity/trivy/master/contrib/junit.tpl
trivy image --format template --template '@junit.tpl' name:tag

CI サービスでの使い方

  • 余計なログを出さないようにする
    • --no-progress を指定する
  • 脆弱性データベースのダウンロードは時間がかかるのでキャッシュを活用する

Docker Registry へのアクセス

trivy からそれぞれのサービスにアクセスするための認証情報は次のように制御できるそうです。

Docker Hub の場合は環境変数

export TRIVY_AUTH_URL=https://registry.hub.docker.com
export TRIVY_USERNAME={DOCKERHUB_USERNAME}
export TRIVY_PASSWORD={DOCKERHUB_PASSWORD}

Amazon ECR の場合は AWS CLI の認証情報。

export AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
export AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
export AWS_DEFAULT_REGION=us-west-2

## あるいは
export AWS_PROFILE=profile

GCR の場合は gcloud の認証情報。

export GOOGLE_APPLICATION_CREDENTIALS=/path/to/credential.json

正規化理論の復習

参考文献

賛否あるけどこの辺の書籍を参考にしました。

サマリ

  • 正規化理論とは
    • RDBMS のテーブル設計の目標は事実を一か所に記録して、関係を定義すること
    • 事実を複数個所に記録していると(重複していると)、どちらかの更新を忘れると一貫した答えが得られなくなってしまう(矛盾が生じてしまう)
    • 矛盾が生じるのを避けるには重複を許さない設計が必要
    • 正規化理論はそのための設計プロセス
  • テーブル設計のプロセス
    • 繰り返しを排除する(第1正規形)
    • 部分的関数従属性を排除する(第2正規形)
    • 推移的関数従属性を排除する(第3正規形、ボイス―コッド正規形)
    • 多値従属性を排除する(第4正規形)
    • 結合従属性を排除する(第5正規形)

個人的な理解

  • 正規化違反を気にしすぎるのもよくない
    • 「第n正規形に違反しているから」といってデータストアとして機能しないわけじゃない
    • データの一貫性が損なわれるリスクを別の部分で担保しているかもしれない
  • とはいえ、リレーショナルデータベースの機能を活用するには違反しないことが望ましい
    • データ構造を無理矢理リレーショナルモデルに合わせるのではなくドキュメントモデルの利用も検討したほうがいい

繰り返しの排除

  • すべての属性がそれ以上分離できない値で構成されること
    • アプリケーションドメインの属性として使用できる範囲の値のみで構成する
  • 繰り返しグループが存在しないこと
    • ある行の属性に複数の値を埋め込まないこと
    • 同じ意味の属性を複数並べないこと

    1NF 第1正規形

    • 表1.1 例:分解する前提でカンマやタブで連結した値を埋め込むのは NG
    • 表1.2 例:course1、course2、course3、みたいに同じ意味の列を複数並べるのは NG
    • 表1.3 例:繰り返しがなくなったので OK

表1.1: 例:分解する前提でカンマやタブで連結した値を埋め込むのは NG

name course grade
桂小五郎 リレーショナルモデル,Javaプログラミング 2
勝海舟 リレーショナルモデル,Ruby on Rails,コンピューターアーキテクチャ 3
坂本龍馬 リレーショナルモデル,コンピューターアーキテクチャ 1

表1.2: 例:course1、course2、course3、みたいに同じ意味の列を複数並べるのは NG

name course1 course2 course3 grade
桂小五郎 リレーショナルモデル Javaプログラミング   2
勝海舟 リレーショナルモデル Ruby on Rails コンピューターアーキテクチャ 3
坂本龍馬 リレーショナルモデル コンピューターアーキテクチャ   1

表1.3: 例:繰り返しがなくなったので OK

name course grade
桂小五郎 リレーショナルモデル 2
桂小五郎 Javaプログラミング 2
勝海舟 リレーショナルモデル 3
勝海舟 Ruby on Rails 3
勝海舟 コンピューターアーキテクチャ 3
坂本龍馬 リレーショナルモデル 1
坂本龍馬 コンピューターアーキテクチャ 1

関数従属性

  • AB
  • 「AはBを決定する」「BはAに従属する」
  • 1つの属性の値(A)が分かれば他の属性の値(B)を特定できる、という性質
  • 例:社員番号(A)が分かれば社員名(B)がわかる
  • 候補キーの部分集合から候補キーに含まれない属性に対する関数従属性
    • 部分的関数従属性
    • 第2正規形を満たす条件
  • 候補キーに含まれない属性から候補キーに含まれない属性に対する関数従属性
    • 推移的関数従属性
    • 第3正規形を満たす条件
  • 候補キーに含まれない属性から候補キーの部分集合に対する関数従属性
    • 推移的関数従属性
    • ボイス―コッド正規形を満たす条件
候補キー
行を特定する最小限の列の集合。複数存在する可能性もあるから候補。
スーパーキー
候補キーに不要な属性も含んでいるキー。

    2NF 第2正規形

  • 第1正規形を満たしていること
  • すべての候補キーについて、候補キーに含まれない属性を特定できるような部分集合が存在しないこと
    • 部分集合=候補キーを構成する属性の全ての組み合わせ
    • 表1.4 例:部分的関数従属性が存在する
      • 候補キーは {name,course,grade}
      • {name}{grade} に関数従属性がある
    • 表1.5表1.6 例:部分的関数従属性を排除
      • {name,grade} を別のテーブルへ分離して関数従属性を排除した

表1.4: 例:部分的関数従属性が存在する

name course grade
桂小五郎 リレーショナルモデル 2
桂小五郎 Javaプログラミング 2
勝海舟 リレーショナルモデル 3
勝海舟 Ruby on Rails 3
勝海舟 コンピューターアーキテクチャ 3
坂本龍馬 リレーショナルモデル 1
坂本龍馬 コンピューターアーキテクチャ 1

表1.5: 部分的関数従属性を排除(a)

name course
桂小五郎 リレーショナルモデル
桂小五郎 Javaプログラミング
勝海舟 リレーショナルモデル
勝海舟 Ruby on Rails
勝海舟 コンピューターアーキテクチャ
坂本龍馬 リレーショナルモデル
坂本龍馬 コンピューターアーキテクチャ

表1.6: 部分的関数従属性を排除(b)

name grade
桂小五郎 2
勝海舟 3
坂本龍馬 1

    3NF 第3正規形

  • 第2正規形を満たしていること
  • 候補キーに含まれない属性Aから候補キーに含まれない属性Bに対する関数従属性が存在しないこと
    • 候補キーでaddressが特定できる、かつ、addressからzipcodeを特定できる場合、候補キーからzipcodeへの推移的関数従属性が存在する

    BCNF ボイス―コッド正規形

  • 第3正規形を満たしていること
  • 候補キーに含まれない属性から候補キーの部分集合に対する関数従属性が存在しないこと
    • 候補キーが曖昧な場合に生じる

多値従属性

  • AB
  • 「AはBの集合を決定する」
  • 1つの属性の値(A)が分かれば、別の属性の集合(B)が特定できる、という性質
    • 属性集合{A,B,C}について、Aを決めるとBCが独立して決まる状態
    • 例:バンド名(A)が分かればメンバーの一覧(B)がわかる
  • 候補キーの部分集合の属性が、候補キーに含まれない属性へ1対nに対応するのが多値従属性
    • 1対1に対応するのが部分的関数従属性
  • 候補キーの部分集合から候補キーに含まれない属性に対する関数従属性
    • 多値従属性(関数従属性の一種)
    • 第4正規形を満たす条件

    4NF 第4正規形

  • 第3正規形を満たしていること
  • 候補キーの部分集合から候補キーに含まれない属性に対する関数従属性が存在しないこと

結合従属性

  • 複数のテーブルへ分離しても、結合して元のテーブルを復元できる性質
    • 第5正規形を満たす条件

    5NF 第5正規形

  • 第4正規形を満たしていること
  • テーブルに候補キー以外の属性が1つしか存在しないこと

不具合対応と障害対応の違い

前提

  • 個人的な意見です。状況によって違う場合もあるのは当然です
  • 想定する場面はソフトウェア開発プロジェクトです
  • 何よりも大事なのは、関係者の間で同じ言葉を違う意味で捉えないようにすることです

不具合対応

  • fault recovery
  • 不具合 = プログラムや設定の誤り
  • 不具合箇所を特定、修正する活動

障害対応

  • troubleshoot
  • 障害 = システムエラーや、不正なデータの混入によりシステムが正常に動作しなくなること
  • エラーや不正なデータを特定、修正する活動

不具合対応と障害対応の違い

  • 不具合対応 は結果(完了しているかどうか)が重要
    • 解消できる原因がある
      • 再発しないことを保証できる
    • 完了したかどうか確認すればわかる
      • 正解がある
    • 手段は問われない
      • 設定変更でも、プログラム改修でも、データメンテナンスでも、システムとして総合的に解決できていればよい
        • 解決できているかどうかが重要
  • 障害対応 は過程が重要
    • タイミング問題など、そもそも再現できない場合がある
      • 再発しないことを保証できない
    • 完了したかどうか確認できない
      • そもそも再現できない場合がある
    • 対応内包は標準化したい
      • 再発時はすみやかに対応したい
      • そのためには対応内容(過程、何をどうしたのか)を標準化しておきたい

だから何

  • 不具合対応 は<<課題管理ツール>>で管理しよう
  • 障害対応 は<<Wiki>>で管理しよう

利用できるオプションの異なる hostname コマンドに対応する

hostname コマンドには複数の形態があるためたまに困ることがあります。

困ること

  • MSYS には net-tools が入ってない
    • coreutilshostname が入ってる
    • 特に Git for Windows のことです
  • CentOSDebian には net-toolshostname が入ってる
    • ただし net-tools とは独立したパッケージになってる
  • 利用できるオプションが違う
    • 前者のコマンドには --help--version しかオプションがない
    • 後者のコマンドにはいろいろオプションがある

という理由で、後者の存在をあてにしているスクリプトの実行に失敗する場合があります。

ワークアラウンド

  • 共通するオプション --version を指定したときの出力文字列を解析します
  • coreutils が含まれているなら coreutils 版で、そうでないなら net-tools 版です

手元では環境変数 PATH の前のほうに(bin より前)、次のようなラッパースクリプトを置くことにしてます。

#!/bin/bash
# hostname

if [[ ! -e /bin/hostname ]]; then
    echo "${HOSTNAME}"
    exit
fi

if /bin/hostname --version | grep coreutils >/dev/null 2>&1; then
    /bin/hostname
    exit
fi

/bin/hostname "$@"

第5回 Chaos Engieering 読書会@リモートのログ

learning.oreilly.com

javaee-study.connpass.com

引き続き Discord によるオンライン開催。

合計 300 ページくらいのところを毎回 30 ページくらい進んでるので、全部で 10 回くらいになるのかなぁ。

次回は 9/12(土曜日)で、Part III Human Factors の 10 Humanistic Chaos から。

javaee-study.connpass.com

対象

  • 8 Capital Oneの採用とカオスエンジニアリングの進化
    • Capital Oneのケーススタディ
    • 実験の設計で気をつけること
    • ツーリング
    • Team Structure
    • Evangelism
    • Conclusion
  • Part III Human Factors(第三部 ヒューマンファクター)
  • 9 Creating Foresight
    • 9.1 Chaos Engineering and Resilience
    • 9.2 Steps of the Chaos Engineering Cycle
    • 9.3 Tool Support for Chaos Experiment Design
    • 9.4 Effectively Partnering Internally
    • 9.5 Conclusion

トピック

ディスカッション

8. Capital Oneの採用とカオスエンジニアリングの進化

銀行は、この証跡を収集し適切な当局に提出するために、必要なガバナンスプロセスとツールを導入している。そのプロセスには法的な意味合いがあり、カオスエンジニアリングのような試みやツールの影響を受けてはならない。

とても大変そう。

Capital Oneのケーススタディ

  • 実験をするのは非本番環境で、実験の結果を反映したものだけが本番環境に反映されている
  • 実験の価値はサポート問い合わせに伴う稼働など具体的な数値に換算している
  • アラートを受け取るということはフェールオーバーやオートスケールできていないことを意味しているため実験は失敗になる
  • SOX 法に準拠したデプロイメントパイプラインは、人間が介入せずにリリースすることが承認されている
  • Blind Resiliency Testing is 何

    • おそらく社内用語
  • 金融系の規制には本番環境とそれ以外の環境は物理的に分離しないといけない、とかそういうのを聞いたことがある

  • 医療システムだとどうなんだろう?
    • オンライン診療とかはできそう
    • 電子カルテ連携とかはダメそう(むしろ政治的にダメそう)
  • 電力系は規制が厳しいことで有名
  • イスラエルのスタートアップには軍隊経験者が多い(体感)

  • カオス実験ができるかどうかは、実験によりどんな影響があるかどうかにかかってるような気がする

実験の設計で気をつけること

  • リスクスコアって誰がどう決めるんだろう
  • なんか基準があるのかな

  • できるだけリスクを回避しようとする雰囲気

  • 学習よりも大事にしていることがあるのかな

ツーリング

カオスエンジニアリングのための適切なツールを選択することが重要であり、それはあなたの会社のビジネスと運用上の目的と一致している。ツールを導入した後は、そのツールを適切なチーム構成でサポートすることが、実践の採用と成功のために重要になる。

Team Structure

大企業ではどんなにチームの繋がりが良くても、今日のソフトウェア・エンジニアリング・スキルセットの革新的な性質のために同じ問題を複数のチームが同時に解決することになり、結果としてツールの拡散が起こりコストと管理上の問題を招いてしまう。

Evangelism

  • ボトムアップで議論が広まる様子が想像できないので見てみたい
  • 立ち上げの最小単位ってなんだろう
    • 1人 SRE が始める、ていうシナリオがありがち

Conclusion

結局のところ、ツールと実践はエンジニアが最善を尽くせるようにするためのものであり、その逆ではない。

信頼性を追求するための活動が、カオスエンジニアリングのプラクティスとうまく適合している様子だった。

Part III. Human Factors(第三部 ヒューマンファクター)

  • 9 Creating Foresight の紹介
  • 10 Humanistic Chaos の紹介
  • 11 People in the Loop の紹介
  • 12 Experiment Selection Problem (and a Solution) の紹介
  • 前のパートより抽象度が高くなりそう

9. Creating Foresight

カオスエンジニアリングには、信頼性をテストするためのプラットフォームを構築したり、Game Daysを実行したりする以外にも、重要なコンポーネントがあります。個々にとってシステムがどのように構造化されているかに関する懸念、アイデア、メンタルモデルを理解し、技術的・人間的な回復力について組織がどこに秀でているかを学ぶことは、コードによって自動化することはできないことである。

カオスエンジニアリングはただのツールという理解が先立ってしまうけど、人間を成長させる特性を自動化することはできないんだよと。

我々の業界で慢性的に投資が不足しているカオスエンジニアリングの段階は,前段階と後段階です。

カオス実験の準備と後始末に投資が少ない。人間にフォーカスすることが多いため、自動化できないからだ。

重要なことは、サイクルの各段階で、成功を最大化するためには、異なるスキルセットと異なるタイプの役割が必要であるということです。これらの要素を最も効果的にするために、これらのスキルセットと考え方(どちらもトレーニングと支援が可能)について学習します。

人間にフォーカスする部分は自動化できないけど、スキルとして学ぶことはできる。

  • メンタルモデル is 何
    • 人間が理解している(仮定している)システムの振る舞いや内部構造

9.1 Chaos Engineering and Resilience

カオスエンジニアリングは脆弱性を発見したり、表面化させたりすることではない。

勘違いしないでね。

予期しないシステムの結果が発生した場合のレジリエンスの文化を構築することです

障害により発生した影響を事実として受け止め、それを活かしていく考え方ということかな。

9.2 Steps of the Chaos Engineering Cycle

大規模な停止が発生したのは、これらの期待の不一致と、固有の仮定について議論する機会がなかったことが原因の一部でした。サービス・ディスカバリー・インフラストラクチャがどのように機能しているかについて、二人が個別に持っていた文脈を考慮すると、両者の仮定は完全に妥当なものでした。ジョシーとマテオはサポートについて明確にこのような会話をしたことはありませんでした。当たり前のことを誰が議論するでしょうか?実際のところ、事件が発生するまではできないのです。

ポテンヒットになってしまいますよと。

実際には、インシデントが起きた時よりも、このような違いについて話し合う方が、よりオープンになることに気づくでしょう。インシデントが発生していないため、結果として、誇張されない心理的な安全の要素があるからです。安全な設定でこれを実験したことを知っていれば、システムの動作に対する恥や不安感が取り除かれます。そして、この感情的な基盤によって、誰が何をして誰がトラブルに巻き込まれるかということに気を取られることなく、私たちは学ぶことに集中することができるのです。

問題が起きてから対応を考えるとどうしても責任の押し付け合いや感情的な摩擦が生じてしまう。 シミュレーションならそうはならずに、理性的な議論ができるだろう。

  • メンタルモデル is 何
    • 人間が理解している(仮定している)システムの振る舞いや内部構造
  • 人によってシステムの捉え方が違うけどどちらが正解でどちらが不正解というものではないので、お互いのメンタルモデルを理解しておくと役に立つよ、みたいな話

9.3 Tool Support for Chaos Experiment Design

  • "API - baseline" と "API - canary" を分けてるのはなんでだろう
    • 実験結果の有意性を判断するには通常のトラフィックの 2% あればよいと判断した
    • フォールトを注入する実験群と、注入しない対照群を用意する必要がある
    • 前者が "API - canary" 後者が "API - baseline"
  • ChAP を開発することはできたけどそれが本当によかったことなのか、という考察
  • 業務を理解している担当者に実験してもらうのは難しいので、理解が浅くても意味のある実験をできそうなアルゴリズムを考案するほうがいいのかな、みたいな前向きな話
  • ツールを作るだけでなく対話が必要でした、という話じゃないかと

9.4 Effectively Partnering Internally

全ての関係者のメンタルモデルのギャップこそが、真の問題がどこにあるかを明らかにするので、訓練された面接担当者は、全関係者のそれぞれのストーリーを収集することが重要だとよく理解しています。カオス実験を知らせるためにも、認知面接が使えます。

問題の出所を検討するには、メンタルモデルの違いを明らかにするのが良い。それを効果的に行えるのが認知面接という手法。

  • ラクティカルな例がまとまっててよい
  • カオスエンジニアリングの Game Day の様子が見たいなぁ

  • カオス実験をする前に仮説として具体的な状況を想像できるようでないといけない感じする

  • 仮説を立てるのが大事なのであって、分からないこと自体は仕方ない、という理解でいいのかなぁ

    • メンタルモデルの違いを発見できるとかそういう効能があるよね、みたいな
  • ブラストラディウス・爆風半径 is 何

    • 障害の影響範囲のこと
  • ストレージサイズ的な意味でメトリクス貯めるのしんどくない ?

    • (無邪気に収集してるとメトリクス監視システムが破綻しそう)
    • 残したい期間に応じてストレージサービスを使い分ける感じ
    • サービスによってダッシュボードの作りやすさが違ってくる

9.5 Conclusion

これらの議論のポイントは、エキスパートのチームがシステムのコンポーネントに関する隠された専門知識を見つけて共有できるようにすることです

カオス実験の専門家ではなく、業務の専門家がカオス実験から学ぶことが大事。

チームは最終的に、効率化された実験計画とその結果としてのメンタルモデルの比較から、より多くを学びます。

プロセスやツールを自動化することで、人間の理解つまりメンタルモデルの相違を明らかにすることへ集中し、学んでいける。

  • ダッシュボードを作る単位は ?

    • 普通はサービス単位に用意しつつ、カオス実験用に複数のサービスを集約したダッシュボードを用意するとか
  • Mackrel のメトリクスチャートにはコメントつけて GitHub の Issue とかにリンクできてよさそうだった

    • 出典がわからず・・・

参考情報

いろいろ並べたけど全部は読めてない。

Java プロジェクトの依存ライブラリの脆弱性を OWASP Dependency Check でチェックする

用語

準備

説明ページを読むと、ダウンロードして実行するだけ、ということがわかります。

Depencency-check cli

Windows (Git Bash) または Linux の場合は次のように準備するといいでしょう。

curl -fsSL --output "${HOME}/Downloads/dependency-check.zip" "https://bintray.com/jeremy-long/owasp/download_file?file_path=dependency-check-5.3.2-release.zip"
mkdir -p "${HOME}/.local"
unzip -d "${HOME}/.local" "${HOME}/Downloads/dependency-check.zip"

dependency-check cli の使用例

最初に実行したときは脆弱性データベースをダウンロードしたりするので、3分くらい余計に時間がかかります。

最低限必要なオプションはこの辺です。

  • format オプション
    • HTML を指定する: Web ブラウザで閲覧できる単一ファイルの HTML レポートを生成します
      • 初期値は HTML だから指定しなくてもいい
    • JUNIT を指定する: いろんな IDE やレポート出力ツールが解釈できる JUnit XML 形式のレポートを生成します
  • out オプション
  • exclude オプション
    • スキャンから除外するファイルパスを Ant のパスマッチャー形式で指定する
    • 複数指定できる
  • scan オプション
    • スキャンするファイルパスを Ant のパスマッチャー形式で指定する
    • 複数指定できる

次のオプションは CI で実行するときに指定すると便利だと思います。

  • failOnCVSS オプション
    • 1から10までの CVSS スコアを指定する
    • 指定した CVSS スコアより高い(つまり危険度が高い)脆弱性を発見したら失敗する
    • 初期値は 11 (つまり失敗しない)
  • junitFailOnCVSS オプション
    • JUnit レポートを生成するときに失敗とみなす CVSS スコアを 1から10 の範囲で指定する
    • 指定した CVSS スコアより高い(つまり危険度が高い)脆弱性を発見したら失敗する
    • 初期値は 0 (つまりなんでも見つけたら失敗する)
# Windows の Git Bash の場合
JAVACMD="${JAVA_HOME}/bin/java" ./.local/dependency-check/bin/dependency-check.bat \
--format HTML \
--out tmp/owasp-report/tsr-van2 \
--exclude '**/.gradle/**' \
--exclude '**/.mvn/**' \
--project 'tsr-van2' \
--scan 'c:/src/tsr-van2/tsr-van2/**/*.jar' \
--scan 'c:/src/tsr-van2/tsr-van2/**/*.js'
# macOS あるいは Linux の場合
./.local/dependency-check/bin/dependency-check.sh \
--format HTML \
--exclude '**/.gradle/**' \
--exclude '**/.mvn/**' \
--out tmp/owasp-report/tsr-van2 \
--project 'tsr-van2' \
--scan 'src/tsr-van2/tsr-van2/**/*.jar' \
--scan 'src/tsr-van2/tsr-van2/**/*.js'

いけてないところ

スキャン対象が pom.xmlbuild.gradle ではなく jarwar

  • cli ツールを使う場合は依存ライブラリを一度集めてからスキャンすることになります
    • Maven プロジェクトなら dependency:copy-dependencies で集めるとかそういう
    • Gradle プロジェクトは自前でタスクを定義する
  • 面倒なので Maven プラグインや Gradle プラグインを使うほうがいいでしょう

Maven プラグイン の使用例

dependency-check-maven

OWASP/ Dependency-Check/ documentation/ dependency-check/ Usage

pom.xmlbuild 要素に次のような記述を追加します。

configuration 要素はリファレンスを見ながらいろいろ設定することになるでしょう。

goal 要素には Maven のゴールを指定します。

                <plugin>
                    <groupId>org.owasp</groupId>
                    <artifactId>dependency-check-maven</artifactId>
                    <version>5.3.2</version>
                    <configuration>
                        <failOnError>false</failOnError>
                        <autoUpdate>true</autoUpdate>
                        <cveValidForHours>24</cveValidForHours>
                        <format>HTML</format>
                        <outputDirectory>${project.build.directory}/owasp-reports</outputDirectory>
                        <scanSet>
                            <fileSet>
                                <directory>${project.basedir}</directory>
                                <includes>
                                    <include>src/main/resources</include>
                                    <include>src/main/webapp</include>
                                </includes>
                            </fileSet>
                        </scanSet>
                        <skipProvidedScope>false</skipProvidedScope>
                        <skipRuntimeScope>false</skipRuntimeScope>
                        <skipDependencyManagement>false</skipDependencyManagement>
                        <assemblyAnalyzerEnabled>false</assemblyAnalyzerEnabled>
                    </configuration>
                    <executions>
                        <execution>
                            <goals>
                                <goal>check</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>

次のようなプラグインゴールが利用できるようになります。

  • dependency-check:check
    • プロジェクト単位でレポートを生成します
  • dependency-check:aggregate
    • 全てのプロジェクトをスキャンした単一のレポートを生成します

実行例。

mvn clean dependency-check:check
mvn clean dependency-check:aggregate

Gradle プラグイン の使用例

github.com/jeremylong/dependency-check-gradle

OWASP/ Dependency-Check/ documentation/ Usage

build.gradle に次のような記述を追加します。

plugins {
    id 'org.owasp.dependencycheck' version '5.3.2'
}

dependencyCheck {
    autoUpdate = true
    analyzedTypes = ['jar', 'war', 'js']
    cveValidForHours = 24
    format = 'HTML'
    outputDirectory = "$buildDir/owasp-reports"
    scanProjects = []
    skipProjects = []
    scanSet = [
        'src/main/resources',
        'src/main/webapps',
    ]
}

次のタスクが利用できるようになります。

check タスクや build タスクの依存タスクに追加すれば、特に意識しないで実行できるようになります。

  • dependencyCheckAnalyze
    • プロジェクト単位でレポートを生成します
  • dependencyCheckAggregate
    • 複数のプロジェクトのレポートを集約します
  • dependencyCheckUpdate
    • ローカルディスクにダウンロードした脆弱性データベースを更新します
  • dependencyCheckPurge
    • ローカルディスクにダウンロードした脆弱性データベースを消去します

実行例。

./gradlew dependencyCheckAnalyze