Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions containers/base/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,28 @@ RUN set -eux; \

ENV PATH="/root/.local/bin:/opt/google-cloud-sdk/bin:${PATH}"

# OpenBao CLI (bao)。devbase の機密のサーバ backend と同じ 2.6 系に固定する (PLAN54)。
# 起動中のコンテナから自分の機密を読み書きし、管理者は管理スクリプトをここから実行する。
# .deb は systemd ユニットやシステムユーザーを伴うため使わず、tar.gz から bao だけを置く。
# 同じリリースの checksums.txt で検証し、一致しなければ展開せずにビルドを止める。
ARG BAO_VERSION=2.6.2
RUN set -eux; \
case "$(dpkg --print-architecture)" in \
amd64) bao_arch="amd64" ;; \
arm64) bao_arch="arm64" ;; \
*) echo "Unsupported architecture for bao: $(dpkg --print-architecture)" && exit 1 ;; \
esac; \
bao_tar="openbao_${BAO_VERSION}_linux_${bao_arch}.tar.gz"; \
bao_base="https://github.com/openbao/openbao/releases/download/v${BAO_VERSION}"; \
cd /tmp; \
curl -fsSL "${bao_base}/${bao_tar}" -o "${bao_tar}"; \
curl -fsSL "${bao_base}/checksums.txt" -o bao-checksums.txt; \
bao_sum="$(grep " ${bao_tar}\$" bao-checksums.txt)"; \
echo "${bao_sum}" | sha256sum -c -; \
tar -xzf "${bao_tar}" -C /usr/local/bin bao; \
rm -f "${bao_tar}" bao-checksums.txt; \
bao version

# 確認
RUN gh --version && node --version && npm --version && aws --version && gcloud --version && session-manager-plugin --version

Expand Down
19 changes: 19 additions & 0 deletions docs/user/cli-reference/03-env.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,25 @@ devbase env exec -- docker compose config

> `devbase env exec -- printenv` のように値を表示するコマンドは、画面共有や端末ログに認証情報がそのまま残ります。実行する場面に注意してください。

## `devbase env token`

起動中の dev コンテナの `~/.vault-token` を、OpenBao の新しい token で置き換えます(backend が
`openbao` のときだけ)。コンテナの中の `bao` の token が切れたときに使います。詳しくは
[機密の保存先を選ぶ](../env-backend.md) の「コンテナの中から `bao` を使う」を参照してください。

```
devbase env token [--print] [--context NAME]
```

| オプション | 説明 |
|---|---|
| なし | 現在地のプロジェクトの起動中の dev コンテナ(サービス `<dev>-<n>`)すべてへ書き、書いたコンテナ名を表示する |
| `--print` | コンテナへ書かず、token だけを標準出力へ出す |
| `--context NAME` | docker context を一時的に上書きする |

プロジェクトの外で実行したとき、起動中の dev コンテナが無いときは、token を発行せずに
終了コード 1 で止まります。一部のコンテナへ書けなかったときも 1 です。

## `devbase env rekey`

誰が機密を復号できるかを変更し、暗号化済みの機密をまとめて暗号化し直します。
Expand Down
4 changes: 2 additions & 2 deletions docs/user/cli-reference/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ devbase の全コマンドの構文、オプション、使用例をまとめた
|---------|------|
| [トップレベルコマンド](01-toplevel.md) | `init` / `status` / `bin/rc` |
| [project グループ](02-project.md) | コンテナのライフサイクル管理・一覧(`up` / `down` / `login` / `ps` / `logs` / `scale` / `build` / `rebuild` / `list`)と非推奨の `container` グループ |
| [env グループ](03-env.md) | 環境変数の管理(`init` / `sync` / `list` / `set` / `get` / `delete` / `edit` / `project` / `keygen` / `encrypt` / `decrypt` / `exec` / `rekey` / `doctor` / `export` / `import`) |
| [env グループ](03-env.md) | 環境変数の管理(`init` / `sync` / `list` / `set` / `get` / `delete` / `edit` / `project` / `keygen` / `encrypt` / `decrypt` / `exec` / `token` / `rekey` / `doctor` / `export` / `import`) |
| [plugin グループ](04-plugin.md) | プラグインの管理(`list` / `install` / `uninstall` / `update` / `info` / `sync` / `migrate` / `repo *`) |
| [snapshot グループ](05-snapshot.md) | スナップショットの管理(`create` / `list` / `restore` / `copy` / `delete` / `rotate`) |

Expand All @@ -27,7 +27,7 @@ graph TD
D --> D4["build [image] / rebuild [name]"]
D --> D2["list [--no-interactive]"]
E --> E1[init / sync / list / set / get / delete / edit / project]
E --> E2[keygen / encrypt / decrypt / exec / rekey / doctor]
E --> E2[keygen / encrypt / decrypt / exec / token / rekey / doctor]
E --> E3[export / import]
F --> F1[list / install / uninstall / update / info / sync / migrate]
F --> F2[repo add / repo remove / repo list / repo refresh]
Expand Down
59 changes: 59 additions & 0 deletions docs/user/env-backend.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,65 @@ OpenBao の KV v2 にはコメント・空行の置き場がありません。`d
「他の誰かが先に書きました」と表示して止まります。黙って上書きすることはありません。
もう一度 `env edit`(または `set`)をやり直してください。

## コンテナの中から `bao` を使う

base イメージには OpenBao の CLI `bao`(サーバと同じ 2.6 系)が入っています。backend が
`openbao` の端末で `devbase up` すると、dev コンテナに次の 2 つが渡り、**再起動せずに**
自分の機密を読み書きできます。

| 渡るもの | 形 |
|---|---|
| 接続先 | 環境変数 `BAO_ADDR`(`backend.yml` の `openbao.url`) |
| token | ファイル `~/.vault-token`(`0600`)。`bao` が既定で読む |

コンテナに置くのは 1 時間で切れる token だけで、`secret_id` はホストから出ません。token を
環境変数にしないのは、`docker inspect` や子プロセスの環境に残るためです。

### 読む・書く

置き場のパスは `-mount=devbase` からの相対で、`<user>` は `backend.yml` の `openbao.user` です。

| 置き場 | パス |
|---|---|
| 個人共通 | `users/<user>/global` |
| 個人のプロジェクト | `users/<user>/projects/<name>` |
| チーム共通(読むだけ) | `team/global` |
| チームのプロジェクト(読むだけ) | `team/projects/<name>` |

```bash
bao kv get -mount=devbase users/<user>/global # 一覧
bao kv get -mount=devbase -field=API_KEY users/<user>/global # 1 キー
bao kv patch -mount=devbase users/<user>/global NEW_KEY=value # 1 キーを足す・変える
```

**`kv put` はパスの中身を丸ごと置き換えます。** 指定しなかったキーは消えるので、1 キーだけを
足す・変えるときは `kv patch` を使ってください。キーを消すのは、ホストの
`devbase env delete --user KEY` が確実です(残すキーを読み直して丸ごと書き戻します)。

起動中のシェルの環境変数は、書き換えても変わりません。今のシェルで新しい値を使うときは
読み直します。次の `devbase up` からはコンテナの環境変数にも載ります。

```bash
export API_KEY="$(bao kv get -mount=devbase -field=API_KEY users/<user>/global)"
```

コンテナで書いた値は、ホストの手元キャッシュ(`secrets/cache/`)には反映されません。ホストの
`devbase up` / `env get` はサーバの現物を読むため、到達できる限り食い違いません。

### token が切れたら

`bao` が `permission denied`(`Code: 403`)を返したら、token の期限(1 時間)が切れています。
**ホストの**プロジェクトのディレクトリで次を実行すると、起動中の dev コンテナすべての
`~/.vault-token` を新しい token に置き換えます。

```bash
devbase env token # 起動中の dev コンテナへ書く
devbase env token --print # token を表示するだけ(手で渡すとき)
```

別ホストの Docker(`project.local.yml` の `docker.context`)で動かしているコンテナにも、同じ
接続先で届きます。`--context NAME` で一時的に上書きできます。

## サーバへ到達できないとき

取得できた機密は、参照ごとに age で暗号化して `secrets/cache/` に控えられます
Expand Down
22 changes: 22 additions & 0 deletions issues/PLAN54_bao-in-container.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,3 +168,25 @@
| 項目 | 誰が決めるか | 期限 |
| --- | --- | --- |
| ~~token を取り直す手段~~ → 決まった: ホストの `devbase env token` が起動中のコンテナの `~/.vault-token` を書き換える(設計の決定 2。(b) `secret_id` をコンテナへ渡す案と (c) OIDC 案は採らない) | 設計 Pull Request のマージで利用者が承認する | 設計 |

## 実装計画

設計は `issues/PLAN54_bao-in-container-design.md`(マージ済み #175)。PLAN55 (#177) が先に入ったため、
`_push_bao_token` の token は `runtime.store_for(root)`(注入と同じ `SecretStore`)から取る
(設計「処理の流れ」の表「PLAN55 の後」)。

| Task | 対象ファイル | 変更内容 | 満たす受け入れ条件 | 進め方 |
| --- | --- | --- | --- | --- |
| 1 | `containers/base/Dockerfile`、`tests/containers/test_base_dockerfile_bao.py` | `ARG BAO_VERSION=2.6.2`、tar.gz + `checksums.txt` を取得し `sha256sum -c`、`bao` だけを `/usr/local/bin` へ | 1・2・10 | 文言を固定するテスト → Dockerfile。実ビルドは手で 1 度 |
| 2 | `lib/devbase/env/openbao.py`、`tests/env/test_openbao.py` | `issue_token()`(期限内なら再ログインしない) | 6 の土台 | 偽サーバで login 回数を固定 → 実装 |
| 3 | `lib/devbase/env/container_token.py`、`tests/env/test_container_token.py` | `push(names, token, runner=)`: `docker exec -i` + `mktemp` → `mv -f`、token は stdin のみ | 8 | runner のスタブで argv / input / 文言を固定 → 実装 |
| 4 | `lib/devbase/commands/container.py`、`tests/commands/test_container_bao.py` | openbao のとき `dev_environment` に `BAO_ADDR`、[5/6] の後に `_push_bao_token`(失敗は警告) | 7 | up の harness で compose 引数と docker exec の有無を固定 → 実装 |
| 5 | `lib/devbase/commands/env.py`、`lib/devbase/cli.py`、`tests/commands/test_env_token.py` | `devbase env token [--print] [--context NAME]`、`SUBCMD_MAP`、`_NO_SECRET_INJECTION` | 6 | 設計の状況表の行ごとにテスト → 実装 |
| 6 | `docs/user/env-backend.md` | 「コンテナの中から `bao` を使う」の節 | F4 | 文書 |

設計からの追加(実装で決めたこと): `cmd_scale` も構成を作り直すため、`up` と同じく `BAO_ADDR` を足し、
増やしたインスタンス(`current_scale + 1`〜)へ token を書く(2026-09-14。設計は `up` だけを挙げていたが、
`scale` で増えたコンテナに `BAO_ADDR` と token が無い状態を作らないため)。

リスク: `container.py` は 1300 行超。触るのは `_run_deploy_pipeline` と `cmd_up` の後処理の数行に限る。
切り戻し: 差分を戻すだけ(永続データなし)。イメージは再ビルドで元に戻る。
12 changes: 11 additions & 1 deletion lib/devbase/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
('project',): ['up', 'down', 'ps', 'login', 'logs', 'scale', 'build', 'rebuild', 'list'],
('container', 'ct'): ['up', 'down', 'ps', 'login', 'logs', 'scale', 'build', 'rebuild'],
('env',): ['init', 'sync', 'list', 'set', 'get', 'delete', 'edit', 'project', 'keygen',
'exec', 'encrypt', 'decrypt', 'rekey', 'doctor',
'exec', 'token', 'encrypt', 'decrypt', 'rekey', 'doctor',
'export', 'import', 'backend'],
('plugin', 'pl'): ['list', 'install', 'uninstall', 'update', 'info', 'sync', 'repo', 'migrate'],
('snapshot', 'ss'): ['create', 'list', 'restore', 'copy', 'delete', 'rotate'],
Expand Down Expand Up @@ -368,6 +368,13 @@ def _add_env_parser(subparsers):
metavar='-- CMD [ARGS...]',
help='Command to run (prefix with -- to pass flags)')

env_token = env_sub.add_parser(
'token',
help='Refresh the OpenBao token in running dev containers (~/.vault-token)')
env_token.add_argument('--print', dest='print_only', action='store_true',
help='Print a token to stdout instead of writing it into containers')
_add_context_arg(env_token)

for name, action in (('encrypt', 'Move plaintext settings into the encrypted store'),
('decrypt', 'Move encrypted settings back to plaintext')):
sub = env_sub.add_parser(name, help=action)
Expand Down Expand Up @@ -803,6 +810,9 @@ def main():
# backend の設定を触るコマンド。設定が壊れている・サーバに届かない状態でこそ
# 実行されるため、注入で先に落ちないようにする。
('env', 'backend'),
# コンテナの bao へ token を届けるだけで、機密の値は要らない。注入するとサーバへの
# 往復が増える (PLAN54)。
('env', 'token'),
})


Expand Down
Loading
Loading