git push や npm install -g のように組み込みルールでは許可されるコマンドを、自分で書いた理由を添えてブロックします。ルールはルールブックのファイルに書き、各スコープの rule.json で読み込むルールブックを指定します。カスタムルールはブロックを追加するだけで、組み込みルールを緩和することはありません。
ルール設定ファイルの場所
CC Safety Net は 2 つのスコープからルールブックを読み込み、マージします。- ユーザースコープ。
~/.cc-safety-net/rules/rule.json(rule init --globalで作成)。すべてのプロジェクトに適用する個人の既定設定に使います。 - プロジェクトスコープ。 プロジェクトルートにある
.cc-safety-net/rules/rule.json。ソース管理にコミットできる、チームやプロジェクト固有のルールに使います。
.cc-safety-net/ があるディレクトリ(通常はホームディレクトリ)では、プロジェクトのパスがユーザー設定そのものになります。そのため、プロジェクトスコープに書き込む rule のサブコマンドは、そこでは実行を拒否します。ユーザー設定ディレクトリでの rule を参照してください。
スコープのマージ
- CC Safety Net はユーザースコープを先に読み込み、両スコープのルールブックを合わせて使います。
- 同じ名前のルールブックが両方のスコープにある場合は、ユーザー側が優先され、プロジェクト側のルールは使われません。警告が報告され、ランタイムは
degradedになります。どちらかの名前を変えれば解消します。 - 各スコープの
overridesは、そのスコープのルールにだけ適用されるため、プロジェクトの設定でユーザーのルールを無効にしたり書き換えたりすることはできません。ユーザーのルールを指定したプロジェクトのオーバーライドや、どのルールにも一致しないオーバーライドのキーは、警告付きで無視されます。 transparent_wrappersとcommand_toolsは、両スコープの内容を合わせて使います。
ルールブックの設定元を管理する
rule.json の rules 配列の各項目は、ルールブックの設定元です。
rule.json を手で編集する代わりに、rule コマンドを使ってください。
--global(-g)を付けます。--only と --ref は公式ルールブックで、各サブコマンドとその出力やエラーは rule で説明しています。
ルールブックはライブファイル
ランタイムはツール呼び出しのたびに各rulebook.json をディスクから読み取るため、保存した編集は次のコマンドから反映されます。存在しない、読み取れない、または無効なルールブックのルールは使われず、ランタイムは degraded を報告します。一度も取得していない GitHub の設定元がある場合は、npx -y cc-safety-net rule update を実行してください。設定の復旧を参照してください。
透過ラッパー
透過ラッパーは、timeout 5 git push のように別のコマンドを実行するコマンドです。CC Safety Net は透過ラッパーを素通りして、その先で実行されるコマンドを検査します。そのため、組み込みルールもカスタムルールも、timeout 5 docker system prune には docker system prune と同じように適用されます。
次の 8 つのラッパーは組み込みで、設定は不要です:caffeinate、exec、nice、nohup、setsid、stdbuf、time、timeout。
チームが rtk のような別のラッパー経由でコマンドを実行しているなら、それを追加します。
- ラッパー名は
^[a-zA-Z][a-zA-Z0-9_-]*$に一致し、ファイル内で一意でなければなりません。 - 予約されたコマンドはラッパーにできません。
git、busybox、rm、find、xargs、parallel、すべてのシェルラッパー、すべてのインタープリター、awk のインタープリターが該当します。 - 追加するのは、子コマンドを書かれたとおりに実行するラッパーだけにしてください。
rule.json に保存されるため、rule.json を読み取れないと失われます。rule.json で宣言する対象範囲を参照してください。
コミュニティ製のシェルツール
プラグインは、エージェントに独自のシェルツールを追加できます。たとえばdsh-ops プラグインは ops_bash と ops_run_background を追加します。CC Safety Net はこれらの名前を知らないため、パスの引数は検査しますが、command をシェルコマンドとしては読みません。宣言するまでは、ops_bash で git reset --hard を実行してもブロックされません。
ツールを宣言すると、CC Safety Net はそのコマンドを解析します。
command_tools 配列が書き込まれます。
ops_bash で git reset --hard を実行すると、git.reset-hard でブロックされるようになります。
- 名前は、エージェントが送るツール名と大文字・小文字まで完全に一致させます。
rule tool addは組み込みのツール名を拒否します。rule tool addの名前のエラーを参照してください。 cwdには、作業ディレクトリを渡す引数の名前を指定します。指定しない場合はworkdir、cwd、working_directoryを読み、どれもなければセッションのワークスペースを使います。作業ディレクトリが空白の場合はtool-call.malformed、存在しないディレクトリの場合はcwd.requested-unusableとして呼び出しを拒否します。"cwd": falseは、スマートフォンやリモートホストなど、別のマシンでコマンドを実行するツールに使います。CC Safety Net はこのツールでは作業ディレクトリの引数を読まないため、上記の拒否はどちらも起きず、セッションのワークスペースを基準に各コマンドを検査します。rm -rf buildのような相対パスは、リモートの作業ディレクトリではなく、このワークスペース内にあるものとして判定されます。
rule.json に保存されるため、rule.json を読み取れないと、そのスコープのツールは失われます。ファイルを手で編集したら npx -y cc-safety-net rule verify を実行してください。
最初のカスタムルールを作る
1
rule.json を作成する
.cc-safety-net/rules/rule.json が作成されます。rule init --example を使うと、.cc-safety-net/rules/example-rules/rulebook.json に例のルールブックも書き込みます。npx -y cc-safety-net rule add example-rules を実行するまでは有効になりません。2
ルールブックを書く
.cc-safety-net/rules/project-rules/rulebook.json を作成します。3
登録する
rule.json に "rules": ["project-rules"] が追加されます。次のコマンドから、git add -A、git add --all、git add . が、指定した理由とともにブロックされます。4
検証する
rule verify は両スコープの rule.json を確認し、各設定元をランタイムと同じ方法で読み込んで、バージョン 2 のフィクスチャを実行します。リモートのコンテンツを取得することはありません。rule.json のスキーマ
rule.json は、有効にするルールブックを選び、オーバーライドを適用し、透過ラッパーとコミュニティ製のシェルツールを宣言します。安全レベル、組み込みの保護、パスの許可と拒否、監査ログの保持期間は別のファイルで設定します。ポリシーを参照してください。
integer
必須
スキーマのバージョンで、
1 でなければなりません。array
ルールブックの設定元を表す文字列のリストです。既定値は空の配列です。設定元の名前はファイル内で一意でなければならず、指定できる設定元は最大 64 個です。
object
<rulebook-name>/<rule-name> をキーとするルールのオーバーライドです。値は、ルールを無効にする "off" か、ルールのブロックメッセージを置き換えるオブジェクトです。オブジェクトでは reason が必須で、intent は任意です。intent を省略すると、ルール自身の intent がそのまま使われます。array
プラグインのシェルツールです。CC Safety Net はその
command を組み込みのシェルツールと同じように解析します。各項目は、ツール名か { "name": "ops_bash", "cwd": "dir" } のようなオブジェクトで、cwd には引数名か false を指定します。既定値は空の配列です。名前は一意でなければならず、組み込みのツール名は指定できません。コミュニティ製のシェルツールを参照してください。intent)の両方を変えるオーバーライドは、次のようになります。
エディターでの rule.json 補完
CC Safety Net は rule.json の JSON Schema を公開しています。エディターにこのスキーマを指定すると、補完と検証が使えます。
rule verify は、有効な rule.json にこの $schema 行がなければ追加します。policy.json のスキーマは公開されていません。
ルールブックのスキーマ
各ルールブックは、それぞれ専用のrulebook.json ファイルに書きます。
integer
必須
ルールブックのスキーマのバージョンで、
1 か 2 でなければなりません。それ以外の値は rulebook_version must be 1 or 2 で検証に失敗します。バージョン 2 のルールを参照してください。string
必須
ルールブックの名前です。ローカルのディレクトリ名、または GitHub の設定元の名前と一致しなければなりません。
string
必須
ルールブックのバージョン文字列です。
string
ルールブックの説明です。
string
ルールブックの作成者です。
array
必須
このルールブックでルールを定義できるコマンドです。
array
任意のフィクスチャです。フィクスチャのスキーマを参照してください。
ルールのスキーマ
以下のフィールドは、rulebook_version 1 のルールを定義します。バージョン 2 では、subcommand と block_args の代わりに match オブジェクトを使います。バージョン 2 のルールを参照してください。
string
必須
ルールブック内で一意な名前で、最大 64 文字です。先頭は英字で、そのあとに英字、数字、ハイフン、アンダースコアを続けます。
string
必須
照合するベースコマンドです。
allowed_commands に含まれていなければなりません。string
照合するサブコマンドです(
add や install など)。省略すると、どのサブコマンドにも一致します。array
必須
ブロックのきっかけになる引数です。1 つ以上必要なため、バージョン 1 のルールではサブコマンドのすべての使い方をブロックすることはできません。その場合はバージョン 2 のルールを使います。
string
必須
ルールがコマンドをブロックしたときに表示するメッセージで、最大 256 文字です。
string
エージェントに伝える意図で、ブロックメッセージのフッターに追加されます。
hard_stop、use_alternative、scope_down、manual_only、stop_and_explain のいずれかです。既定値は manual_only です。バージョン 2 のルール
"rulebook_version": 2 を設定すると、サブコマンドと引数の組み合わせではなく、厳密なコマンドパスで照合します。gcloud compute の下の delete をブロックするバージョン 1 のルールは、コマンド中のどこかにそのトークンがあれば一致するため、gcloud compute instances create delete もブロックします。コマンドパスが ["compute", "instances", "delete"] のバージョン 2 のルールは、これをブロックしません。
バージョン 2 のルールは、name、command、reason、intent をバージョン 1 から引き継ぎ、subcommand と block_args を match オブジェクトに置き換えます。
array
必須
コマンドの後ろに、この順で続かなければならないコマンドの語です。空でない文字列からなる空でない配列で指定します。パスは空にできないため、
aws のすべての呼び出しのように、コマンドのあらゆる呼び出しに一致するルールは作れません。array
これらのトークンのうち少なくとも 1 つが、引数の中にそのままの形で現れる必要があります。空でない一意な文字列からなる空でない配列です。省略すると、引数にかかわらずコマンドパスだけで照合します。
array
これらのトークンのいずれかが引数の中にそのままの形で現れると、ルールは一致しません。空でない一意な文字列からなる空でない配列です。
subcommand や block_args が残っているルールは、rules[0].subcommand: not supported in rulebook_version 2 と rules[0].block_args: not supported in rulebook_version 2 で検証に失敗します。
フィクスチャのスキーマ
フィクスチャは、意図した動作を記録するものです。CC Safety Net はフィクスチャのコマンドをパースしてルールブックのルールで評価しますが、実行はしません。string
必須
フィクスチャのシェルコマンドです。
string
必須
blocked か allowed のどちらかです。string
コマンドをブロックするはずのルールです。
blocked のフィクスチャでは必須です。rule add、rule update、rule verify が評価します。blocked のフィクスチャは指定したルールが最初に一致すれば合格し、allowed のフィクスチャはどのルールにも一致しなければ合格します。
rule add と rule update は、フィクスチャが失敗した設定元を書き込む前に拒否します。失敗したフィクスチャは、tests 内のインデックスで示されます。
rule verify では、example-rules/rulebook.json: tests[0]: ... のように、各行の先頭にルールブックのファイルが付きます。
照合の挙動
どちらのバージョンも、トークンをそのままの形で、大文字と小文字を区別して照合します。正規表現、glob、部分一致はありません。
--all-files は --all に一致しません。ルールは順番に評価され、最初に一致したルールがブロックします。
ルールは入れ子のコマンドにも適用されます。rm のルールがあれば、bash -c 'rm -r ./tmpdir'、eval 'rm -r ./tmpdir'、呼び出された関数の本体のいずれもブロックされます。組み込みのアナライザーが扱うコマンドも対象です。
バージョン 2 のグローバルオプション
値を取るグローバルオプションを認識できるのは、aws、gcloud、az だけです。それ以外のコマンドでは、git -C repo push のように値を別の語として書いたオプションがあると、ルールは一致しません。Terraform の -chdir=DIR は 1 つのトークンなので読み飛ばされます。
リリースチャネルには別のルールが必要です。gcloud beta compute instances delete は ["compute", "instances", "delete"] に一致しません。["beta", "compute", "instances", "delete"] で 2 つ目のルールを書いてください。
バージョン 1 はオプションに続けて書いた値を誤読する
バージョン 1 はオプションに続けて書いた値を誤読する
CC Safety Net は
-Cfoo を -C foo ではなく -C -f -o -o として扱います。そのため、-f をブロックするルールが、オプションに続けて書かれた値に誤って一致することがあります。ルールが照合するのはコマンドで、ファイルパスではない
カスタムルールが照合するのは、シェルコマンドとその引数です。エージェントが独自の読み取りツールや編集ツールで開くファイルは見えないため、~/.zshrc のようなファイルをルールで保護することはできません。ファイルやフォルダーへのアクセスをすべてブロックするには、policy.json の secret_protection.deny_paths に追加してください。拒否パスは読み取りもブロックします。
例
すべての git push をブロックする
command_path: ["push"] で any_args を指定しないバージョン 2 のルールは、引数にかかわらず git push をブロックします。バージョン 1 のルールでは、block_args に 1 つ以上の引数が必要なため、これはできません。
timeout は透過ラッパーなので、このルールは timeout 5 git push もブロックします。一方、git -C repo push には一致しません。バージョン 2 のグローバルオプションを参照してください。
ルールを 1 つ無効にする
カスタムルールを無効にするには、そのルールブックを指定しているスコープのrule.json で、overrides に <rulebook-name>/<rule-name> のキーを値 "off" で追加します。このキーはブロックメッセージに表示されます。
rule update でオーバーライドが元に戻ることはありません。git.push-force のような組み込みルールを無効にするには、policy.json を使います。ブロックされたコマンドを許可するを参照してください。
npm のグローバルインストールをブロックする
ブロックメッセージの形式
ブロックメッセージ全体のレイアウトはブロック時の表示で説明しています。カスタムルールでは、どのルールブックがブロックしたかが分かるように、ルールブック名とルール名が先頭に付きます。<rulebook-name>/<rule-name> は、rule.json の overrides でルールを無効にするときや、理由を置き換えるときに使うキーでもあります。
旧形式の設定を移行する
CC Safety Net は、旧形式のインライン設定ファイル(.safety-net.json と ~/.cc-safety-net/config.json)を読み込まなくなりました。それらのルールは何もせず、ランタイムも警告を出しません。残っているファイルは、npx -y cc-safety-net doctor と rule verify が Legacy inline rule configs are ignored として報告します。
rule migrate には --global がなく、両方のスコープを移行します。ホームディレクトリで実行すると、プロジェクト側の移行は省略されます。ユーザー設定ディレクトリでの rule migrate を参照してください。
インラインのファイルは、次の構成に変換されます。
カスタムルールの設定が無効な場合
読み込みに失敗したカスタムルールの設定は、コマンドを拒否するのではなく破棄されます。ほかの設定元と組み込みルールは適用され続け、ランタイムはdegraded を報告します。ブロックが減っても通知されないため、ルールを編集したときやアップグレードしたときは npx -y cc-safety-net status を実行してください。設定の復旧を参照してください。