Cosign と SLSA による aqua CLI Version Manager の Security 改善
CLI ツールを YAML でバージョン管理できるツール aqua を開発しています。
aqua v1.26.0 から Cosign や SLSA を活用し Security を改善した話を紹介します。
aqua ではこれまでも checksum の検証や Policy as Code といったセキュリティの改善を行ってきました。
今回は aqua を使ってツールをインストールする過程で改竄 (tampering) されるのを防ぐようにしました。
aqua では以下のような改竄のリスクがあります。
- aqua-installer (shell script) の改竄
- aqua の改竄
- package の改竄
これらのリスクに対し、以下のような対策を施しました。
- aqua-installer の改竄
- aqua-installer の実行前に script の checksum を検証する手順をドキュメントで案内
- aqua の改竄
- aqua のリリース時に SLSA Provenance を生成
- aqua-installer で aqua の install 時に SLSA Provenance を検証
- package の改竄
- Cosign と SLSA Provenance による検証をサポート
Docker を用いた検証環境の作成
環境を汚さずにコマンドを実行するために Docker を使います。
docker run --rm -ti alpine:3.17.0 sh
apk add curl bash sudo
adduser -u 1000 -G wheel -D foo
visudo # Uncomment "%wheel ALL=(ALL) NOPASSWD: ALL"
su foo
mkdir ~/workspace
cd ~/workspace
export PATH="${AQUA_ROOT_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/aquaproj-aqua}/bin:$PATH"
aqua-installer の検証
従来 aqua-installer を使って次のようなワンライナーで aqua をインストールしていたかと思います。
curl -sSfL https://raw.githubusercontent.com/aquaproj/aqua-installer/v1.1.2/aqua-installer | bash
しかしこれは aqua-installer が改竄されていないか検証していないので少々危険です。
そこで aqua-installer の実行前に checksum を検証しましょう。
curl -sSfL -O https://raw.githubusercontent.com/aquaproj/aqua-installer/v2.0.2/aqua-installer
echo "acbb573997d664fcb8df20a8a5140dba80a4fd21f3d9e606e478e435a8945208 aqua-installer" | sha256sum -c
chmod +x aqua-installer
aqua-installer を更新する度にコード(checksum)を修正する必要がありますが、 aqua-installer の更新頻度は高くないのでさほど問題にはならないでしょう。
aqua の検証
aqua の GitHub Releases を見ると SLSA Provenance multiple.intoto.jsonl
があるのが分かるかと思います。
aqua-installer を実行して aqua をインストールします。
aqua-installer は v2.0.0 から aqua の SLSA Provenance を検証します。
./aqua-installer
ログを見ると SLSA Provenance が検証されているのが分かります。
INFO[0001] verify a package with slsa-verifier aqua_version=1.26.2 env=linux/arm64 new_version=v1.26.2 package_name=aquaproj/aqua package_version=v1.26.2 program=aqua registry=
Verified signature against tlog entry index 9918167 at URL: https://rekor.sigstore.dev/api/v1/log/entries/24296fb24b8ad77a4f5de5310f955deac79a5e8f16363b66a038bc6436fd330668a2933d69c75228
Verified build using builder https://github.com/slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@refs/tags/v1.4.0 at commit d37dec79a9b96c85592eb24d69f9972cbd176f9a
この検証をサポートするために aqua-installer に大きな改修を入れました。破壊的変更を含むので v2 に major update しています。
破壊的な変更点としては、 aqua のインストール先を指定できなくなりました。
従来のデフォルトのインストール先にインストールされるので、元々インストール先を指定していない場合は関係ありません。
aqua には aqua 自身を更新する update-aqua
というコマンドがありますが、このコマンドでも SLSA Provenance を用いて aqua を検証しています。
aqua-installer v2 では内部的に aqua update-aqua を実行しています。
package の検証
Cosign と SLSA Provenance による検証をサポートしました。
といってもこれは package 側が対応していないと検証できませんし、現状対応しているパッケージはほとんどありません。
今後 Cosign や SLSA が普及してくると対応しているパッケージも増えてくるかと思います。
tflint は Cosign による keyless signing に対応しています。
Standard Registry ではこの署名を使って tflint を検証する設定が入っています。
このように以下の 2 つの条件を満たす必要があります。
- aqua でインストールするツール側が Cosign による署名か SLSA Provenance を公開している
- Registry 側でそれらを使って検証する設定をしておく
tflint を aqua でインストールしてみましょう。
aqua.yaml を生成します。
aqua init
tflint の checksum file が検証されているのを確認するため、 Checksum Verification を有効化してください。
vi aqua.yaml # Checksum Verification を有効化
---
# 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.110.0 # renovate: depName=aquaproj/aqua-registry
packages:
tflint をインストールします。
aqua g -i terraform-linters/tflint
aqua i
ログを見ると Cosign がインストールされているのが分かります。
INFO[0000] download and unarchive the package aqua_version=1.26.2 env=linux/arm64 package_name=sigstore/cosign package_version=v1.13.1 program=aqua registry=
INFO[0008] downloading a checksum file aqua_version=1.26.2 env=linux/arm64 package_name=sigstore/cosign package_version=v1.13.1 program=aqua registry=
aqua は Cosign を自動で内部的にインストール
するので、ユーザーが Cosign をインストールする必要はありません。
内部的にインストール
とはどういう意味かというと、 $AQUA_ROOT_DIR/pkgs
配下にはインストールするけど PATH
配下にシンボリックリンクは作成しないという意味です。 aqua は PATH
関係なく絶対パスを指定して Cosign を実行します。
内部的にインストールされる Cosign のバージョンは現状 aqua 内部にハードコードされています。
tflint のインストール時に tflint の checksum file が Cosign で検証されています。
INFO[0002] verify a checksum file with Cosign aqua_version=1.26.2 env=linux/arm64 package_name=terraform-linters/tflint package_version=v0.44.0 program=aqua registry=standard
tlog entry verified with uuid: fab3e75f7e01ac757d8ddab411a7fd0c8b35c4ea2d0cb31c4c5bfdbe7ac5cf42 index: 9877371
Verified OK
次に SLSA Provenance の検証も見てみましょう。
aquaproj/example-go-slsa-provenance が SLSA Provenance をサポートしているのでインストールしてみます。
aqua g -i aquaproj/example-go-slsa-provenance
aqua i
SLSA Provenance を用いて検証されています。
INFO[0000] verify a package with slsa-verifier aqua_version=1.26.2 env=linux/arm64 package_name=aquaproj/example-go-slsa-provenance package_version=v0.1.2 program=aqua registry=standard
Verified signature against tlog entry index 9476343 at URL: https://rekor.sigstore.dev/api/v1/log/entries/24296fb24b8ad77a92eb2665ca9575614bc6b0833267eca755ca5d2e8d5a563c2b70c310dad3c0f6
Verified build using builder https://github.com/slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@refs/tags/v1.4.0 at commit 4581df55e03c5155801ad10b88b19e42f99d8861
v0.1.1 をインストールしてみましょう。このバージョンはわざと改竄してあります。
vi aqua.yaml # v0.1.1 に変更
aqua i
期待通り失敗しました。
INFO[0002] verify a package with slsa-verifier aqua_version=1.26.2 env=linux/arm64 package_name=aquaproj/example-go-slsa-provenance package_version=v0.1.1 program=aqua registry=standard
Verified signature against tlog entry index 9476343 at URL: https://rekor.sigstore.dev/api/v1/log/entries/24296fb24b8ad77a92eb2665ca9575614bc6b0833267eca755ca5d2e8d5a563c2b70c310dad3c0f6
ERRO[0004] install the package aqua_version=1.26.2 env=linux/arm64 error="verify a package with slsa-verifier: run slsa-verifier's verify-artifact command: expected tag 'refs/tags/v0.1.1', got 'refs/tags/v0.1.2': tag used to generate the binary does not match provenance" package_name=aquaproj/example-go-slsa-provenance package_version=v0.1.1 program=aqua registry=standard
FATA[0004] aqua failed aqua_version=1.26.2 env=linux/arm64 error="it failed to install some packages" program=aqua
さいごに
以上、 Cosign と SLSA を用いた改竄対策を紹介しました。
ユーザーが特に意識することなく自動で検証されるため、ユーザー体験を損なうことなくセキュリティを改善することができました。
Renovate に続き、 Cosign や SLSA もうまく活用した OSS になったのではないかと思います。
今後 Cosign や SLSA がより普及し、多くのツールを安全にインストールできるようになることを期待していますし、自分も何かしら Contribution できればいいなと思っています(すでにちょっとしています) 。
Discussion