起動スクリプト
os.startup_scripts は、成果物イメージ向けに上限付きの systemd ワンショット作業を作成します。各エントリはシェル コマンド、必要なパッケージ、実行ユーザー、順序付けユニットを宣言します。
起動スクリプトは、run_as が別の指定をしない限り、root 相当のコードです。インストール スクリプトと同じ審査を受けなければなりません。
正規の形状
{
"os": {
"startup_scripts": [
{
"name": "write-build-marker",
"description": "Create a local readiness marker after networking is available.",
"command": "set -Eeuo pipefail\ninstall -d -m 0755 /var/lib/example\nprintf '%s\\n' ready > /var/lib/example/build-ready",
"packages": [],
"run_as": "root",
"after": "network-online.target"
}
]
}
}フィールドは description と command であり、旧来の script フィールドではありません。run_as と after も snake_case です。after は配列ではなく、systemd ユニット文字列 1 つです。
スキーマは最大 32 件のエントリと上限付きのコマンドサイズを受け入れます。検証は空のコマンドと NUL バイトを拒否しますが、シェル内容を安全にも冪等にもしません。
再試行と部分失敗に備えた設計
ブートは、一部の副作用が発生したあとに中断されることがあります。別の呼び出しが安全に完了するか、検査可能な明確な状態で終了するようにスクリプトを書いてください。
良いパターンには次があります。
- 一時ファイルへ書き込み、検証してから原子的に名前を変更する;
- ユーザー、ディレクトリ、構成エントリが既に存在するかを確認する;
- 所有者とモードを明示するために
installを使う; set -Eeuo pipefailを適用し、想定される非ゼロ結果を意図的に扱う;- 上限付きのネットワーク タイムアウトと有限の再試行回数を使う; そして
- 必要な手順がすべて成功したあとにだけ準備完了マーカーを書く。
準備完了の確認として sleep に頼らないでください。実際の依存関係をプローブしてください。
外部ダウンロード
curl ... | sh は避けてください。初回ブートで成果物を取得しなければならない場合:
- 証明書検証付きの HTTPS を使う;
- 期待する成果物またはソースのバージョンを固定する;
- 実行前に暗号ダイジェストまたは承認済み署名を検証する;
- 接続タイムアウトと合計タイムアウトを設定する;
- 検証が失敗したら閉じた失敗にする; そして
- 資格情報や署名付き URL をログに残さない。
真にオフラインまたは再現可能な動作にするには、初回ブートでダウンロードする代わりに、審査済みの内容をイメージまたは承認済みパッケージ リポジトリに含めてください。
秘密情報
平文の資格情報をレシピ、コマンド、URL、生成されたマーカーに埋め込まないでください。レシピ JSON とビルド ログは保持される証拠であり、運用者に見えることがあります。承認済みのデプロイ時エンロールメントまたは秘密配布の仕組みを使い、得られる資格情報を対象に限定してください。
実行アイデンティティ
権限の低いサービス アカウントを優先してください。root が必要な場合は、コマンドを最小の特権ステップに縮小し、ファイル所有者を明示してください。run_as が、ユニット開始前に作成されるアカウントを指していることを確認してください。
検証
ユニットの終了ステータスだけでなく、結果をテストしてください。
{
"type": "file_contains",
"description": "The startup unit wrote its readiness marker.",
"params": {
"path": "/var/lib/example/build-ready",
"content": "ready"
}
}2 回目のブート、利用できない依存関係、中断された初回実行からの回復もテストしてください。失敗時は systemctl status とユニット ジャーナルを確認してください。