ハッカーに「訪問」されてから慌てないために
エンジニアの間では、よく「即席」の習慣が見受けられます。コードを書き、イメージをビルドし、アプリが動くのを確認したら、すぐに本番環境へデプロイしてしまうのです。しかし、その時の爽快感は、セキュリティを軽視していればすぐに惨劇へと変わります。
私は以前、2年前の古いライブラリの脆弱性が原因で、システムが乗っ取られるのを目の当たりにしました。その時、チーム全員が徹夜でコンテナを隔離し、パニック状態でパッチを当てることになりました。その苦い経験から学んだのは、「セキュリティはビルドの段階から優先すべき(シフトレフトセキュリティ)」ということです。システムが稼働してから脆弱性を探すのでは遅すぎます。
実際、node:latestのような巨大なベースイメージには、プルした直後に600以上の脆弱性(CVE)が含まれていることがあります。そこでTrivyの出番です。これはDockerイメージやKubernetesマニフェストの不備を、ワークフローを停滞させることなくあぶり出す非常に強力なツールです。
なぜTrivyはこれほど普及しているのか?
高速にスキャンでき、面倒なインストールやデータベース設定が不要なツールを探しているなら、Trivyこそが「運命のツール」です。Aqua Securityが開発したこのオープンソースツールは、多くのコンポーネントを的確にスキャンできます:
- OSパッケージ: Alpine, Ubuntu, RHELなどのOSパッケージに含まれる脆弱性を検出。
- 言語パッケージ: Python (pip), Node.js (npm), Go, Javaなどのライブラリ内の脆弱性を調査。
- Infrastructure as Code (IaC): Dockerfile, Kubernetes, Terraformの設定ミスをスキャン。
最大の利点は、Trivyがデーモンを必要とせず、エージェントのインストールも不要なことです。バイナリファイルを1つダウンロードするだけで、すぐにスキャンを開始できます。GitHub ActionsやGitLab CIなどのCI/CDパイプラインへの組み込みも非常に柔軟です。
実践:Trivyのインストールと使い方を3ステップで解説
1. クイックインストール
Linuxでは、次の1行のコマンドだけでTrivyをシステムに導入できます:
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin v0.48.3
実行後、trivy --versionと入力して確認してください。バージョンが表示されれば、脆弱性ハンティングの準備は完了です。
2. 実際のDockerイメージをスキャン
具体的な数字を比較してみましょう。まず、フル版のpython:3.9イメージをスキャンしてみます:
trivy image python:3.9
何百ものエラーが表示されるはずです。次に、重要度が極めて高い脆弱性のみに絞り込むために、severityパラメータを使用します:
trivy image --severity HIGH,CRITICAL python:3.9-slim
結果はかなりスッキリします。これを見れば、どのパッケージをアップグレードすべきか、あるいはDistrolessやAlpineのような、より安全なベースイメージに切り替えるべきかが一目でわかります。
3. Kubernetes設定ファイルのチェック
TrivyはYAMLファイルもスキャンできます。例えば、deployment.yamlファイルがあり、コンテナに過剰なroot権限を与えていないか確認したい場合:
trivy conf ./k8s-manifests
CPU/RAMの制限を忘れていたり、コンテナをprivilegedモードで実行していたりすると、即座に警告が表示されます。こうした些細なミスが、ハッカーにクラスター全体の制御権を奪われるきっかけになります。
GitHub Actionsによるセキュリティの自動化
脆弱性スキャンを個人の記憶に頼ってはいけません。GitHub Actionsを使用して、新しいコードがプッシュされるたびに自動スキャンを実行するようにしましょう。もしCRITICALな脆弱性が見つかった場合、パイプラインを自動停止させ、マージを拒否するように設定します。
以下は、私がよく使用する最小構成の.github/workflows/security.ymlファイルです:
name: セキュリティスキャン
on:
push:
branches: [ main ]
jobs:
trivy-scan:
runs-on: ubuntu-latest
steps:
- name: コードのチェックアウト
uses: actions/checkout@v3
- name: イメージのビルド
run: docker build -t my-app:${{ github.sha }} .
- name: Trivyの実行
uses: aquasecurity/trivy-action@master
with:
image-ref: 'my-app:${{ github.sha }}'
exit-code: '1'
severity: 'CRITICAL,HIGH'
exit-code: '1'を設定することで、深刻な脆弱性が見つかった場合にパイプラインが赤くなり停止します。これにより、本番環境にデプロイする前に、チームが強制的にセキュリティ問題に対処するように促せます。
脆弱性の山に圧倒されないための「鉄則」
初めてスキャンした時、リストの長さにショックを受けるかもしれません。慌てずに、以下の3つのルールを適用してください:
--ignore-unfixedフラグを使用する: 修正パッチが既に存在する脆弱性のみに集中します。ベンダーから修正方法が提供されていないものは、混乱を避けるために一時的に無視しましょう。- Slim/Alpineイメージを優先する: 500以上の脆弱性がある
node:latestの代わりにnode:alpineを使いましょう。脆弱性の数は10以下に抑えられ、管理が格段に楽になります。 - 定期スキャンをスケジュールする: 今日の時点でクリーンなイメージが、来週も安全であるとは限りません。CronJobを作成して、サーバーで稼働中のイメージを週に一度再スキャンするようにしましょう。
おわりに
Trivyはシステムを完璧に保護する魔法の杖ではありません。しかし、一般的なリスクの90%を阻止する助けになります。障害対応に何時間も費やす代わりに、5分かけてこのツールを導入しましょう。エンジニアの皆さんが、夜中にサーバーのトラブルで叩き起こされることなく、ぐっすり眠れることを願っています!

