こんにちは!インフラやセキュリティの世界へようこそ。
これからサーバーOSの要塞化や、現代の開発に欠かせない「コンテナイメージの脆弱性スキャン」について、一緒に学んでいきましょうね。
セキュリティの専門用語って、最初は「CVE」だの「CI/CD」だのと英語の呪文のようで、少し身構えてしまいますよね。でも大丈夫です。実はどれも、私たちの身の回りにある「防犯の仕組み」と全く同じ考え方で成り立っているんです。
今回は、新人のIT担当者や開発者のあなたに向けて、攻撃者がどこを狙ってくるのか、そしてどうやってガチガチの守りを作ればいいのかを、泥臭い現場のリアルな知見も交えながら優しく紐解いていきますよ!
—
1. 家の鍵をかけるのと同じ? コンテナの「防犯」の基本
皆さんは、お出かけするときに玄関の鍵を閉めますよね。では、もし「鍵が壊れている古いタイプのドア」や「窓が全開の部屋」に、世界中からアクセスできるとしたらどうでしょう?……想像するだけでゾッとしますよね。
私たちが普段コンテナ(Dockerなど)で動かしているアプリケーションも、これと全く同じです。
コンテナのベースとなる「イメージ(OSやライブラリの詰め合わせパック)」には、過去に見つかった不具合やセキュリティの弱点、いわゆる「CVE(共通脆弱性識別子)」が含まれていることがよくあります。
攻撃者は、自動化されたボットを使って、世界中のサーバーの「鍵の壊れたドア」を日々探し回っています。もし、私たちが古いライブラリが入ったままのコンテナを本番環境(=お家の中)にポイッとデプロイ(配置)してしまったら……? 泥棒に「どうぞお入りください」と言っているようなものなんです。
だからこそ、「お家に鍵をかけるのと同じように、デプロイする前に必ず中身をチェックして、危ないやつは外で食い止める」という仕組みが必要になります。それが今回学ぶ「コンテナイメージの脆弱性スキャンとCI/CDパイプライン統合」というわけです。
—
2. 現場の現実:なぜ「ビルド時」にスキャンしなければならないのか?
現場でよくある失敗が、「とりあえず動くものを作って、本番サーバーにデプロイした後にセキュリティチェックをする」というアプローチです。
これ、実は大間違いなんですよ。
泥棒が家に入ってきてから「あ、鍵が壊れてた!」と気づいても、もう手遅れですよね。最悪の場合、家の中の宝箱(データベース)はすでに荒らされています。
だからこそ、開発のベルトコンベヤーである「CI/CDパイプライン(GitHub ActionsやGitLab CIなど)」の途中でスキャンを入れる必要があります。
プログラムを書いて「よし、コンテナを作ろう!」とビルドしたまさにその瞬間に、セキュリティの警備員(スキャナー)を走らせるんです。
ここで重大な脆弱性(CriticalやHighレベルのCVE)が見つかったら、「このコンテナは危険だから、絶対にデプロイさせない!」と自動でブロック(門前払い)する。これが、現代のインフラエンジニアが実践している鉄壁のガバナンスです。
—
3. 実践!Trivyを使ったCI/CDパイプラインの構築
百聞は一見に如かず。実際に、人気のオープンソース脆弱性スキャナーであるTrivy(トリビー)を使って、GitHub Actions上でこの仕組みを作ってみましょう!
「Trivyって難しそう……」と思うかもしれませんが、驚くほどシンプルに動かせますよ。以下の設定ファイル(YAML形式)を、リポジトリの .github/workflows/security-scan.yml として配置してみてください。
name: Container Security Scan
# コードがプッシュされたり、プルリクエストが作成されたりしたときに発動します
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
scan:
name: Trivy Vulnerability Scan
runs-on: ubuntu-latest
steps:
# 1. リポジトリのコードをチェックアウト(手元に持ってくる)
- name: Checkout code
uses: actions/checkout@v4
# 2. テスト用のコンテナイメージをビルドする
- name: Build a Docker image
run: docker build -t my-app:${{ github.sha }} .
# 3. Trivyを使ってコンテナイメージをスキャンする(ここが主役!)
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
image-ref: 'my-app:${{ github.sha }}'
format: 'table' # 結果を分かりやすくテーブル形式で表示
exit-code: '1' # 脆弱性が見つかったらビルドを失敗(エラー)させる重要設定!
ignore-unfixed: true # まだ修正パッチが出ていない脆弱性はいったん無視する(運用上の工夫)
severity: 'CRITICAL,HIGH' # 致命的(CRITICAL)か重大(HIGH)なものだけを対象にする
この設定のポイント
exit-code: '1'の部分が肝心です。ここで、セキュリティ的にNGなものが見つかった瞬間にパイプライン全体を「失敗」させ、危険なコンテナがこれ以上先(本番環境)に進むのを物理的に阻止します。severity: 'CRITICAL,HIGH'で、本当に危険なものだけに絞ってチェックすることで、開発者が「アラートが多すぎて心が折れる…」という状態を防ぎます。
—
4. セキュリティは「面倒くさい」を味方につける仕組みづくり
今回は、コンテナイメージの脆弱性スキャンとCI/CD統合について、防犯の例えを交えながらお話ししてきましたがいかがでしたでしょうか?
セキュリティ対策というのは、「気合で気をつける」ものではありません。人間は必ずうっかりミスをしますし、忙しいとチェックを忘れてしまいます。だからこそ、今回紹介したような「自動化された仕組み(パイプライン)」に頼るのが、最高かつ最も確実な防犯対策なのです。
最初は覚えることが多くて大変に感じるかもしれませんが、一歩ずつ、今日できる設定から環境に取り入れていきましょう。あなたの書いたコードとインフラが、サイバー攻撃からしっかりと守られる安全なものになるよう、これからも一緒に学んでいきましょうね!
コメント