本文の内容は、2022年9月19日にEduardo Mínguezが投稿したブログ(https://sysdig.com/blog/container-image-scanning-for-azure-pipelines-with-sysdig/)を元に日本語に翻訳・再構成した内容となっております。
Sysdig Secureを使用して、Azure Pipelinesに脆弱性やバッドプラクティスがないかコンテナイメージをスキャンするのは、簡単なプロセスです。この記事では、その方法についてステップバイステップの例を説明していきます。
以下のProof of Contentでは、Azure Pipelinesで sysdig-cli-scanner
を活用する方法が紹介されていました。可能ではありますが、Sysdigが公式にサポートしているわけではないので、ドキュメントを確認し、これらの手順を自分の環境に適応させることをお勧めします。
このブログ記事は、2022年4月以降に利用可能な脆弱性スキャナーに焦点を合わせています。レガシースキャナーをご利用の方は、公式ドキュメントをご参照ください。
こちらからパイプラインの定義に直行できます。
Sysdig Secureによるイメージ脆弱性スキャン
イメージスキャンにより、DevOpsチームは、コンテナが本番環境にデプロイされる前、またはイメージが任意のコンテナ・レジストリにプッシュされる前に、パイプラインの初期段階で既知の脆弱性を検出し、コンテナのビルド構成を検証することにより、セキュリティをシフトレフトさせることができます。これにより、問題の迅速な検出と修正、本番環境での脆弱性の回避、クレデンシャル漏洩の回避、本番環境へのデリバリー時間の短縮が可能になり、そのすべてがより安全な方法で行われます。Sysdigのイメージスキャンプロセスは、ImageConfigのチェック(機密情報の漏洩など)、OSパッケージだけでなくサードパーティパッケージ(java、pythonなど)のチェックなど、さまざまなルールを含むようにカスタマイズ可能なポリシーに基づいています。
Sysdigの脆弱性スキャンは、スキャン手順を実行する場所によってイメージの分類が異なってきます。
- パイプライン:
sysdig-cli-scanner
ツールで実行されるランタイム段階(開発者のワークステーション内、CI/CDパイプライン内など)の前。 - ランタイム:実行ノードでイメージが実行され、Sysdigエージェントによってスキャンが実行される場合
Sysdig 脆弱性のUIスクリーンショット
本記事では、ベストプラクティスとして採用されているAzure Pipelinesを使ったパイプラインステップでのスキャンの実行方法について説明します。
コンテナイメージに対してスキャナーを実行するのは、
sysdig-cli-scanner
ツールに以下のようないくつかのフラグ(詳細は公式ドキュメントを参照)を付けて実行するのと同じくらい簡単です。SECURE_API_TOKEN=<your-api-token> ./sysdig-cli-scanner --apiurl <sysdig-api-url> <image-name> --policy <my-policy>
イメージはツールを実行するホスト、ラップトップ、パイプラインを実行するコンテナ上でローカルにスキャンされ、スキャン結果のみがSysdig Secureのバックエンドに送信されます。
Azureパイプライン
Azure DevOpsは、コードリポジトリ、レポート、プロジェクト管理、自動ビルド、ラボ管理、テスト、およびリリース管理などのツールをチームに提供します。Azure パイプラインはAzure DevOpsバンドルのコンポーネントで、コードに対するテストの実行、gitリポジトリにコミットがプッシュされたときのコンテナイメージのビルド、コンテナイメージに対する脆弱性スキャンの実行など、CI/CDタスクの実行を自動化するものです。脆弱性スキャンのためのAzure パイプライン
Azureパイプラインは、YAMLファイルに記述されたタスクの一括を定義し、イベントが発生したときに自動的に実行されます。イベントとは、通常、リンク先のリポジトリに新しいコミットやプルリクエストが発生したときのことです。Azureパイプラインのステップ例図
これにより、自動的にビルドしてレジストリ(Azure Container Registryなど)にイメージをプッシュし、Kubernetesにデプロイすることができます。
このブログ記事の説明に使う例では、Azureパイプラインを起動するGitHubのリポジトリにコミットをプッシュしていきます。そして、パイプラインはプロジェクトをローカルイメージにビルドし、脆弱性をスキャンして、コンテナレジストリに公開します。
AzureパイプラインとSysdigのスキャン手順図
アプリケーションの例
具体的な例を示すために、GitHub リポジトリに保存されている、8080/tcp
ポートをリッスンし、リクエストされたパスに基づいた文字列を返す簡単な golang アプリケーションを利用します。package main import ( "fmt" "log" "net/http" ) func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "I love %s!\n", r.URL.Path[1:]) } func main() { http.HandleFunc("/", handler) log.Fatal(http.ListenAndServe(":8080", nil)) }
このシンプルなプログラムを、ビルドしてコンテナ化します。
FROM golang:1.18-alpine as builder WORKDIR /app COPY . . RUN go mod download RUN go build -o /love FROM alpine COPY --from=builder /love /love EXPOSE 8080 ENTRYPOINT [ "/love" ]
Azure パイプラインに GitHub リポジトリへのアクセス権を与える
Azure は GitHub リポジトリにアクセスし、プロジェクトのビルドとコンテナイメージの生成に必要なコードをダウンロードします。また、パイプラインを構成するタスクが含まれるazure-pipelines.yaml
ファイルも同じリポジトリに格納されているので、それを取得することになります。すでに Azure DevOps アカウントを取得し、プロジェクトを作成していると仮定して、次のステップに従って Azure Pipelines に GitHub リポジトリへのアクセスを許可します:
リポジトリが空の場合、空白の yaml ファイルから始まり、Azure Pipelines のエディターで修正するか、コードを直接 GitHub にプッシュする必要があります。
今回の場合、パイプラインはすでにGitHubのリポジトリにファイルとして作成されているので、そこに表示されているコードは、リポジトリに存在するものです。パイプラインの各ステップについては、後ほど詳しく説明します。
Azure Pipelines にコンテナイメージを公開するためのアクセス権を与える
今回は、コンテナイメージを公開するために quay.io を活用します。すでに持っていると仮定して:
- quay.ioのアカウント
- そして ‘空の’ quay リポジトリ
必要なものは:
- ‘robot’ アカウントを作成する
- そして、Azure パイプラインサービスへの接続を設定します。
では、行っていきます:
connection nameを忘れないようにしましょう。後でレジストリにアクセスする際に使用します。
Azure Pipeline のシークレット変数
sysdig-cli-scanner
は、スキャン結果を Sysdig アカウントに送信できるようにするために Sysdig API トークンを必要とします。これは Sysdig アカウントの Settings -> User profile セクションにあり(詳しくは Retrieve the Sysdig API Token を参照)、シークレット変数を用いて暗号化して保存するとよいでしょう。
Sysdig Secure でイメージスキャンするための Azure パイプライン YAML 定義
これですべてが揃ったので、パイプラインの定義を掘り下げましょう。基本的には、以下のようなワークフローになります。- コンテナイメージをビルドし、ローカルに保存する
- 必要に応じて、
sysdig-cli-scanner
ツールをダウンロードします。 - スキャンを実行する
- コンテナイメージをリモートレジストリにプッシュする
このワークフローでは、Azure パイプラインのキャッシュを利用して、バイナリ、データベース、コンテナイメージが利用可能な場合は、ダウンロードを回避することもできます。
それでは、パイプラインのさまざまなステップを見ていきましょう。
この例で使用するバージョンは、Azure agent version: ‘2.209.0’、Image: ubuntu-20.04 (Version: 20220828.1, Included Software: https://github.com/actions/runner-images/blob/ubuntu20/20220828.1/images/linux/Ubuntu2004-Readme.md), Runner Image Provisioner: 1.0.0-main-20220825-1 and Sysdig-cli-scanner version 1.2.6-rc (commit: 17bb64a) となります。
レガシースキャナーを使用する場合、パイプラインの定義が異なります。そのため、sysdiglabs/secure-inline-scan
コンテナイメージを使用する必要があります。sysdiglabs/secure-inline-scan-example リポジトリで提供されている例を参照してください。
準備
ごく標準的な設定で、メインブランチにプッシュしたときにトリガーされ、デフォルトのコンテナイメージ(ubuntu-latest)が使われます。trigger: - main pool: vmImage: ubuntu-latest
また、異なるステップで使用されるいくつかの変数を定義しています。
- アセットが保存される
CACHE_FOLDER
- Sysdig Secure API のエンドポイント (
SYSDIG_SECURE_ENDPOINT
) - イメージの詳細 (
SYSDIG_SECURE_ENDPOINT
) - そして、以前に作成したコンテナレジストリへの接続名 (
REGISTRY_CONNECTION
)
variables: CACHE_FOLDER: $(Pipeline.Workspace)/cache/ SYSDIG_SECURE_ENDPOINT: "https://eu1.app.sysdig.com" REGISTRY_HOST: "quay.io" IMAGE_NAME: "e_minguez/my-example-app" IMAGE_TAG: "latest" REGISTRY_CONNECTION: "quayio-e_minguez"
キャッシュ
バイナリやアセット(脆弱性データベースなど)のキャッシュを設定し、毎回ダウンロードするのを避けます。- task: Cache@2 inputs: key: | sysdig-cli-scanner-cache | "$(Agent.OS)" | "$(CACHE_FOLDER)/sysdig-cli-scanner" | "$(CACHE_FOLDER)/latest_version.txt" | "$(CACHE_FOLDER)/db/main.db.meta.json" | "$(CACHE_FOLDER)/scanner-cache/inlineScannerCache.db" restoreKeys: | sysdig-cli-scanner-cache | "$(Agent.OS)" sysdig-cli-scanner-cache path: $(CACHE_FOLDER) displayName: Cache sysdig-cli-scanner and databases
コンテナイメージのキャッシュを設定し、毎回ダウンロードするのを回避します。
- task: Cache@2 displayName: Docker cache inputs: key: 'docker | "$(Agent.OS)" | cache' path: $(Pipeline.Workspace)/docker cacheHitVar: CACHE_RESTORED
コンテナイメージがあれば、キャッシュからロードします。
- script: | docker load -i $(Pipeline.Workspace)/docker/cache.tar displayName: Docker restore condition: and(not(canceled()), eq(variables.CACHE_RESTORED, 'true'))
ビルド
Docker@2タスクでコンテナイメージをビルドします。- task: Docker@2 inputs: command: 'build' Dockerfile: 'love/Containerfile' buildContext: 'love/' repository: $(REGISTRY_HOST)/$(IMAGE_NAME) tags: $(IMAGE_TAG) addPipelineData: false addBaseImageData: false
このビルドプロセスでは、1つのタグにつき1つのコンテナイメージを生成します。コミットハッシュやコミットタグのような異なるタグでコミットごとに複数のイメージをビルドすることもできますが、ここではシンプルにしています。
スキャン
必要な場合のみ、最新版のsysdig-cli-scanner
バイナリをダウンロードします。- script: | curl -sLO https://download.sysdig.com/scanning/sysdig-cli-scanner/latest_version.txt mkdir -p $(CACHE_FOLDER)/db/ if [ ! -f $(CACHE_FOLDER)/latest_version.txt ] || [ $(cat ./latest_version.txt) != $(cat $(CACHE_FOLDER)/latest_version.txt) ]; then cp ./latest_version.txt $(CACHE_FOLDER)/latest_version.txt curl -sL -o $(CACHE_FOLDER)/sysdig-cli-scanner "https://download.sysdig.com/scanning/bin/sysdig-cli-scanner/$(cat $(CACHE_FOLDER)/latest_version.txt)/linux/amd64/sysdig-cli-scanner" chmod +x $(CACHE_FOLDER)/sysdig-cli-scanner else echo "sysdig-cli-scanner latest version already downloaded" fi displayName: Download the sysdig-cli-scanner if needed
スキャナーを実行します。これが本番!ご覧の通り、超簡単です。
- script: | $(CACHE_FOLDER)/sysdig-cli-scanner \ --apiurl $(SYSDIG_SECURE_ENDPOINT) \ --console-log \ --dbpath=$(CACHE_FOLDER)/db/ \ --cachepath=$(CACHE_FOLDER)/scanner-cache/ \ docker://$(REGISTRY_HOST)/$(IMAGE_NAME):$(IMAGE_TAG) \ displayName: Run the sysdig-cli-scanner env: SECURE_API_TOKEN: $(TOKEN)
ノート:
sysdig-cli-scanner
ツールで必要とされるように、シークレット変数 TOKEN を環境変数に変換しています。最終タスク
コンテナイメージをリポジトリにプッシュします:- task: Docker@2 displayName: Push the container image inputs: containerRegistry: $(REGISTRY_CONNECTION) repository: $(IMAGE_NAME) command: push tags: $(IMAGE_TAG) addPipelineData: false addBaseImageData: false
今後のパイプラインの実行に使用するコンテナイメージを保存します:
- script: | mkdir -p $(Pipeline.Workspace)/docker docker save $(docker images -q) -o $(Pipeline.Workspace)/docker/cache.tar displayName: Docker save condition: and(not(canceled()), or(failed(), ne(variables.CACHE_RESTORED, 'true')))
パイプラインの実行
最後に、パイプラインを実行し、Azure で動作するのを確認する準備ができました!GitHub リポジトリにコミットした後、Azure ウェブコンソールでパイプラインが動作しているのを確認できます。以下はパイプラインの結果です。
Azureパイプラインの出力成功画面
ご覧の通り、うまくいきました。スキャンはきちんと終了し、1秒で実行されました。
Sysdig Secureにおけるイメージスキャン結果
Sysdig Secureに戻り、これらの結果をさらに分析することができます。レガシースキャナーの結果は若干異なりますので、詳しくは公式ドキュメントをご覧ください。
Sysdig脆弱性スキャン、問題発見0件のスクリーンショット
この基本的なアプリケーションでは脆弱性は発見されませんでしたが(やった!)、https://github.com/sysdiglabs/dummy-vuln-app などの別のアプリケーションを見ると、いくつか発見されていることが分かります。
Sysdig 脆弱性スキャンといくつかの問題点のスクリーンショット
Sysdigの脆弱性スキャンUIで、いくつかの脆弱性が発見されたスクリーンショット
すでに修正されている脆弱性や悪用可能な脆弱性をフィルタリングすることができるので、最も緊急性の高い脆弱性に絞って修正・更新することができます。
Sysdigの脆弱性スキャンのUIで、すでに修正が提供されている脆弱性でフィルタリングされた脆弱性スクリーンショット
脆弱性だけでなく、ベストプラクティスではないものも見ることができます:
失敗したポリシーのリストを表示するSysdig脆弱性スキャンのUI
まとめ
Sysdigを使うと、Azure DevOps Pipelinesで作成したイメージを実に簡単なプロセスでスキャンすることができます。ローカルスキャン機能のおかげで、インフラストラクチャーを離れることなく私たちのイメージをスキャンすることができ、ローカルでビルドされたイメージもスキャンすることができます。CI/CDパイプラインの早い段階で問題を検出することで、イメージスキャンは、DevOpsチームがセキュリティをシフトレフトさせ、本番環境への納期を改善し、本番環境でイメージを実行する信頼性を高めることを可能にします。
Azure MarketplaceでSysdig Secure DevOps Platformをご購入ください!
Sysdigは、Azure Marketplaceで簡単にご購入いただくことができます。