💧

aqua CLI Version Manager が checksum の検証をサポート

2022/10/10に公開

CLI ツールを YAML でバージョン管理できるツール aqua を開発しています。

https://aquaproj.github.io/

https://zenn.dev/topics/aquaclivm

aqua v1.20.0 からツールのインストール時に checksum の検証がサポートされたので紹介します。

https://aquaproj.github.io/docs/reference/checksum/

Checksum の検証とは

checksum の検証とは、ツールのインストール時にダウンロードされた asset の checksum が期待される checksum と同じかどうか比較し、等しい場合のみツールをインストールすることで、 asset の改ざんを防ぐ機能のことです。

ツールのインストール時に checksum を検証することで、 asset が悪意のあるものに置き換えられていることを検出し、インストールを未然に防ぐことが出来ます。

checksum の検証だけでは防げないパターンも当然ありますが、それでも checksum の検証がセキュリティ的に重要なことに変わりはありません。

Getting Started

Getting Started

aqua の checksum の検証機能の細かな仕様を説明する前に、
具体的な使い方を見てみましょう。といっても checksum の検証は自動で行われるので使い方は特に変わりません。

まずは aqua を v1.20.0 以上に update してください。

aqua init

デフォルトでは checksum の検証機能は無効になっています。
aqua.yaml を更新して有効化してください。

aqua.yaml
---
# aqua - Declarative CLI Version Manager
# https://aquaproj.github.io/
checksum:
  # https://aquaproj.github.io/docs/reference/checksum/
  enabled: true
  require_checksum: true
registries:
- type: standard
  ref: v3.72.0 # renovate: depName=aquaproj/aqua-registry
packages:

ここでは tfcmt を aqua でインストールしてみます。
既に tfcmt がインストール済みの場合、 uninstall してください。

$ aqua which tfcmt
/Users/shunsukesuzuki/.local/share/aquaproj-aqua/pkgs/github_release/github.com/suzuki-shunsuke/tfcmt/v4.0.0/tfcmt_darwin_arm64.tar.gz/tfcmt
$ rm -R /Users/shunsukesuzuki/.local/share/aquaproj-aqua/pkgs/github_release/github.com/suzuki-shunsuke/tfcmt/v4.0.0
$ aqua g -i suzuki-shunsuke/tfcmt
$ aqua i
INFO[0000] download and unarchive the package            aqua_version=1.20.0 env=darwin/arm64 package_name=suzuki-shunsuke/tfcmt package_version=v4.0.0 program=aqua registry=standard
INFO[0001] downloading a checksum file                   aqua_version=1.20.0 env=darwin/arm64 package_name=suzuki-shunsuke/tfcmt package_version=v4.0.0 program=aqua registry=standard

従来どおり tfcmt をインストールできました。
aqua.yaml と同じディレクトリに aqua-checksums.json というファイルが生成されているので見てみます。

aqua-checksums.json
{
  "checksums": [
    {
      "id": "github_release/github.com/suzuki-shunsuke/tfcmt/v4.0.0/tfcmt_darwin_arm64.tar.gz",
      "checksum": "372986BFADDBFEB680329341568FC4FBA0D6FA651B941BF4154585B7BAAA67DB",
      "algorithm": "sha256"
    }
  ]
}

tfcmt の checksum がファイルに記録されています。
tfcmt は GitHub Releases に checksum ファイルを公開しているので、そこから checksum は取得されています (tfcmt_4.0.0_checksums.txt)。

checksum がちゃんと検証されていることを確認するために、
checksum を書き換えて tfcmt を再インストールしてみましょう。
checksum がちゃんと検証されていれば、インストールは失敗するはずです(本来は asset を改ざんして検証すべきですが、面倒なので checksum のほうを改ざんしています)。

$ cp aqua-checksums.json aqua-checksums.json.orig # 書き換える前にバックアップを取っておく
$ vi aqua-checksums.json # checksum の末尾を 0 に変更
$ diff aqua-checksums.json aqua-checksums.json.orig # 変更内容を確認
5c5
<       "checksum": "372986BFADDBFEB680329341568FC4FBA0D6FA651B941BF4154585B7BAAA67D0",
---
>       "checksum": "372986BFADDBFEB680329341568FC4FBA0D6FA651B941BF4154585B7BAAA67DB",

$ rm -R /Users/shunsukesuzuki/.local/share/aquaproj-aqua/pkgs/github_release/github.com/suzuki-shunsuke/tfcmt/v4.0.0
$ aqua i
INFO[0000] download and unarchive the package            aqua_version=1.20.0 env=darwin/arm64 package_name=suzuki-shunsuke/tfcmt package_version=v4.0.0 program=aqua registry=standard
ERRO[0001] install the package                           actual_checksum=372986BFADDBFEB680329341568FC4FBA0D6FA651B941BF4154585B7BAAA67DB aqua_version=1.20.0 env=darwin/arm64 error="checksum is invalid" expected_checksum=372986BFADDBFEB680329341568FC4FBA0D6FA651B941BF4154585B7BAAA67D0 package_name=suzuki-shunsuke/tfcmt package_version=v4.0.0 program=aqua registry=standard
FATA[0001] aqua failed                                   aqua_version=1.20.0 env=darwin/arm64 error="it failed to install some packages" program=aqua

期待通り失敗しました。
aqua-checksums.json の checksum を正しいものに戻せば install できるようになるはずです。

cp aqua-checksums.json.orig aqua-checksums.json # もとに戻す
aqua i # 今度は install できる

ちなみに checksum の検証は Lazy Install の際にも行われます。

aqua-checksums.json はツールのインストール時に自動で更新されますが、 aqua update-checksum コマンドを実行して更新することも出来ます。実行してみましょう。

$ aqua update-checksum # [-a] [-deep]
INFO[0000] updating a package checksum                   aqua_version=1.20.0 env=darwin/arm64 package_name=suzuki-shunsuke/tfcmt package_registry=standard package_version=v4.0.0 program=aqua
aqua-checksums.json
aqua-checksums.json
{
  "checksums": [
    {
      "id": "github_release/github.com/suzuki-shunsuke/tfcmt/v4.0.0/tfcmt_darwin_amd64.tar.gz",
      "checksum": "346d43e34ee990c26ebcbc80936bea6d6f524bcc446aa74d1f07c42708fc480b",
      "algorithm": "sha256"
    },
    {
      "id": "github_release/github.com/suzuki-shunsuke/tfcmt/v4.0.0/tfcmt_darwin_arm64.tar.gz",
      "checksum": "372986bfaddbfeb680329341568fc4fba0d6fa651b941bf4154585b7baaa67db",
      "algorithm": "sha256"
    },
    {
      "id": "github_release/github.com/suzuki-shunsuke/tfcmt/v4.0.0/tfcmt_linux_amd64.tar.gz",
      "checksum": "e950763e64504e40a45c75c81a35d115f98f164264e159e4e4b7e2534d3d8087",
      "algorithm": "sha256"
    },
    {
      "id": "github_release/github.com/suzuki-shunsuke/tfcmt/v4.0.0/tfcmt_linux_arm64.tar.gz",
      "checksum": "8ce944ccaf7ff5a150b256d75d8fe3d04ba741d5586bb5f100b9df80294f14fa",
      "algorithm": "sha256"
    },
    {
      "id": "github_release/github.com/suzuki-shunsuke/tfcmt/v4.0.0/tfcmt_windows_amd64.tar.gz",
      "checksum": "2228e167f3ddf61e6ccfd30648cf649f7b18d98eb6b2150e6c3522183628bda9",
      "algorithm": "sha256"
    },
    {
      "id": "github_release/github.com/suzuki-shunsuke/tfcmt/v4.0.0/tfcmt_windows_arm64.tar.gz",
      "checksum": "5435b0d4cca909f752dce456fd186bef2de994f7d1c24665fa8507e9d6019e5b",
      "algorithm": "sha256"
    }
  ]
}

現在の platform (OS, Architecture) だけでなく、 tfcmt がサポートしている全ての platform の checksum が記録されています。

以上が aqua の checksum の検証の基本的な使い方です。
以下でより詳細な説明をしていきます。

checksum の source

各 package の checksum は以下の優先順位で取得されます。

  1. aqua-checksums.json
  2. 各 package が提供している checksums.txt 的なファイル (e.g. tfcmt_4.0.0_checksums.txt)
  3. download された asset から計算

2 に関しては、ファイルを提供していないパッケージも少なからず存在します。

aqua update-checksum command

aqua update-checksum

aqua update-checksum command は aqua.yamlpackages で定義されている全ての package の checksum を取得し、 aqua-checksums.json に記録します。
デフォルトでは各 package が提供しているファイルからのみ checksum を取得します。つまりファイルを提供していない package に関しては checksum が更新されません。
-deep option をつけると、ファイルを提供していない package に関しては asset をダウンロードして checksum を計算します。

デフォルトでは global configuration (AQUA_GLOBAL_CONFIG) は無視されますが、 -a option をつけると global configuration の aqua-checksums.json も更新されます。

aqua-checksums.json

aqua.yaml と同じディレクトリ上の aqua-checksums.json または .aqua-checksums.json が参照されます。

aqua-checksums.json が必要な理由

aqua-checksums.json というファイルが必要な理由は以下のとおりです。

  • Cache (毎回 checksum のファイルをダウンロードしてくるのは効率が悪い)
  • checksum のファイルを提供していない package にも対応するため
  • package が提供する checksum のファイルが改ざんされても asset の改ざんを検出できるようにするため

CI で aqua-checksums.json を自動で更新する

Automate updating aqua-checksums.json in CI

aqua-checksums.json は基本的に Git で管理する想定ですが、
その場合 aqua.yaml の更新に合わせて aqua-checksums.json も更新する必要があります。
特に Renovate で package の update を自動化している場合 aqua-checksums.json の更新も CI で自動化するべきでしょう。

そこで aqua-checksums.json の update を自動化する Action を提供しています。

https://github.com/aquaproj/update-checksum-action

サンプル workflow: https://github.com/aquaproj/example-update-checksum

やってることは単純で、 CI で aqua update-checksum -deep を実行し、 aqua-checksums.json が更新されたら Pull Request の head に commit を push しています。
なので pull_request event を hook する想定になっています。

aqua.yaml での checksum の設定

aqua.yaml's checksum configuration

checksum:
  enabled: true # default は false
  require_checksum: true # default は false

require_checksumtrue の場合、 checksum が aqua-checksums.json または 各 package が提供するファイルから取得できない場合にインストールに失敗します。
逆に言うと、デフォルトでは checksum が取得できない場合はツールは checksum の検証なしにインストールされ、 asset から計算された checksum が aqua-checksums.json に記録されます。
true にしたほうがより安全と言えるでしょう。

Registry での checksum の設定

Registry's checksum configuration

各 package が提供する checksum のファイルに関しては、 Registry で設定する必要があります。

https://github.com/aquaproj/aqua-registry/blob/v3.72.0/pkgs/suzuki-shunsuke/tfcmt/registry.yaml#L13-L20

この設定がない場合、その package が提供する checksum のファイルを取得することは出来ません。
その場合でも aqua-checksums.json に checksum が記録されていれば checksum の検証は可能です。

Standard Registry のサポート状況

上述の通り、各 package が提供する checksum のファイルに関しては、 Registry で設定する必要があります。
Standard Registry の最新バージョンでは checksum のファイルを提供している package に関しては全て設定してあります。

ただし、 checksum のファイルを提供していない package の少なからず存在しますし、もれもあるかもしれません。
900 近い package の設定はかなり大変です。

基本的に最新バージョンを使うようにしてください。古いバージョンで問題が発生した場合、 update することで解決する可能性があります。

さいごに

以上、 aqua の checksum の検証について紹介しました。
checksum を検証することでツールの改ざんを検出し、悪意のあるコードの実行を防ぎ、よりセキュリティを強化することが出来ます。
また、 aqua-checksums.json の更新を CI で自動化することで運用負荷を減らし、利便性を損なわないようにしました。

何か問題があった場合、 GitHub Issue で報告してもらえると助かります。
GitHub Discussions でフィードバックも受け付けていますので、よろしくおねがいします。

Discussion