Files
maestro/docs/operations/bash-sandbox-provisioning.md
T
oss-sync 57702b4f34
CI / build-and-test (push) Canceled after 0s
sync: update from private repo (2336949a)
2026-09-17 11:29:31 +00:00

6.9 KiB
Raw Blame History

Bash サンドボックス 本番プロビジョニング手順 (aao)

順序厳守: 先に「2. パッケージのプリベイク」を完了してから「4. 設定切替」を行う。逆順だと、サンドボックス内で pip install は拒否され、かつパッケージも無い状態になり、python3 を使う既存タスク(office 処理・data 処理等)が全滅する。

0. 前提

  • 本番 worker は aao ホスト上の Node プロセスとして動く(alpine コンテナではない)。bwrap は --ro-bind /usr でホストの /usr をサンドボックスに持ち込むため、プリベイク先はホストのシステム python の site-packages。/home 配下の venv はサンドボックスに mount されず見えないので不可。
  • アクセス: ssh aao(user@your-host)。落とし穴: root でビルドしない / DB は maestro.db( 参照)。

1. bwrap / python の確認・導入

ssh aao
# bwrap (bubblewrap) と user namespace
which bwrap || sudo apt-get install -y bubblewrap
bwrap --ro-bind / / true && echo "bwrap OK" || echo "bwrap NG — user namespace を有効化する必要あり"
# user namespace が無効なら(Debian/Ubuntu):
#   sudo sysctl -w kernel.unprivileged_userns_clone=1
#   永続化: /etc/sysctl.d/ に kernel.unprivileged_userns_clone=1 を追記
# python3 + pip
which python3 pip3 || sudo apt-get install -y python3 python3-pip

2. パッケージのプリベイク(システム python へ)

リポジトリの runtime/python-requirements.txt をホストのシステム python に入れる。読み取り専用 bind されるので全サンドボックスから import 可能になる。

# リポジトリの最新を pull 済みの前提
cd <maestro repo on aao>
# 推奨: 付属スクリプト(冪等・import 検証付き)。権限が要る場合は sudo を付ける
sudo bash scripts/prebake-python.sh
#   ↑ これは内部で `pip3 install --break-system-packages -r runtime/python-requirements.txt`
#     を実行し、最後に全パッケージの import を検証する。
# 注: `scripts/build-all.sh` は最後にこの prebake を自動実行する(--skip-python で無効化)。
#     ただし build-all を sudo 無しで動かす運用では system へ書けず失敗(非致命的に警告)するため、
#     その場合は上記のように prebake を別途 sudo で実行すること。
#
# distro パッケージを優先したい場合(C 拡張のビルド回避):
#   sudo apt-get install -y python3-numpy python3-pandas python3-pil python3-lxml python3-bs4 python3-matplotlib
#   残り (pypdf, pymupdf, pdfplumber, openpyxl, xlsxwriter, xlrd, odfpy, striprtf,
#         python-docx, python-pptx, markdownify, markdown, tabulate,
#         python-dateutil, charset-normalizer) のみ pip

3. プリベイク検証

サンドボックス外(ホスト)で全 import が通ることを確認:

python3 -c "import pypdf, fitz, pdfplumber, docx, pptx, openpyxl, xlsxwriter, xlrd, odf, striprtf, bs4, lxml, markdownify, markdown, numpy, pandas, tabulate, dateutil, matplotlib, PIL, charset_normalizer, yaml; print('all imports OK')"

fitz は pymupdf。失敗するものがあれば runtime/python-requirements.txt を見直すか apt で補う。

4. 設定切替

config.yaml の safety セクション:

safety:
  bash_sandbox: always   # bwrap 必須・不在なら起動失敗(本番推奨)

worker を再起動: scripts/server.sh restart。起動ログに [startup] bash sandbox enabled — bwrap verified が出れば OK。bwrap 不在なら always は起動失敗する(fail-closed)。

auto のままでも bwrap があればサンドボックスは効く。always は「bwrap が無ければ動かさない」明示の本番ガード。

5. 切替後の統合検証(設計 Task 9)

テストタスクを 1 件流し、Bash ツールで以下を実行して期待結果を確認:

# 1) シークレットが見えない
python3 -c "import os; print(os.environ.get('MCP_ENCRYPTION_KEY'))"     # → None
# 2) 他タスク dir / config に到達不可
cat ../../config.yaml 2>&1 || echo "blocked-as-expected"
# 3) ネット到達不可(内部サービス)
python3 -c "import socket; socket.create_connection(('10.0.0.10',8080),2)" 2>&1 || echo "net-blocked-as-expected"
# 4) プリベイク済みパッケージが使える
python3 -c "import pypdf, fitz, pandas; print('ok')"                    # → ok
# 5) install は拒否される(消えるインストールにならない)
pip install requests 2>&1   # → "Package installation is not available ... これは preinstalled ..."

加えて、既存の office 処理 / data 処理系 piece のタスクを数件流し、--unshare-net + プリベイクで完結することを確認(dogfooding)。不足パッケージが出たら runtime/python-requirements.txt に追加 → 手順 2 を再実行(実行時 pip install は恒久的に不可)。

6. ロールバック

safety:
  bash_sandbox: auto     # bwrap があれば使い、無ければ hardened-whitelist にフォールバック
  # もしくは off(bwrap を使わない。env スクラブは維持。デバッグ用)

scripts/server.sh restart。コード変更不要、設定のみで戻せる。

bwrap が壊れているホストで戻す場合は、これだけでは起動しない(#1235)。auto の hardened フォールバックには外向き通信を遮断する仕組みが無いので、遮断を選んだまま(bash_allow_network 既定の false)だと起動時に断られる。この状況で戻すなら次のいずれか。

状況 設定
bwrap は動く(プロビジョニングをやめたいだけ) 上のまま。bash_allow_network は false のまま
bwrap が動かない bash_allow_network: true を併記する。bwrap を直したら false へ戻すこと——これは表明ではなく生きたスイッチで、bwrap が動く状態のまま true だと本当に外向き通信が開く
そもそも隔離を切る bash_sandbox: off。断りの対象外なので、通信の設定は触らなくていい

bash_unrestricted: true を入れている場合は、bash_sandbox を何にしても bwrap が要る。戻すときは bash_unrestricted: false も併せて戻す。

補足: Docker イメージ運用の場合

Dockerfile (node:22-alpine) には bash bubblewrap python3 py3-pip + pip install -r runtime/python-requirements.txt(--break-system-packages)を追加済み。ただし alpine/musl では pandas/numpy/lxml/Pillow/pymupdf の wheel 解決にビルド依存が要る場合があるため、イメージビルドを実機で検証すること(pymupdf>=1.24 に pin 済)。コンテナ運用では features: nesting=1(user namespace)が前提。