Skip to content

Latest commit

 

History

History
171 lines (121 loc) · 7.06 KB

chapter-advance-2.md

File metadata and controls

171 lines (121 loc) · 7.06 KB

Chapter Advance 2 Conftest & Open Policy Agent (OPA)

ここでは、Conftestを利用したポリシーチェックについて学びます。
Conftestではポリシーの定義をOpen Policy Agent(OPA)でも使われているRegoという言語を用いて行います。

Open Policy Agent(OPA)

OPAは、オープンソースの汎用的なポリシーエンジンです。ポリシーに違反した情報を発見し、事前に定義されたアクションを実行する仕組みで、Regoという言語を使用してポリシーを定義します。 主な特徴は以下となります。

  • 軽量で汎用性のあるOSSのポリシーエンジン
  • Kubernetes専用というわけではなく、YAML、JSONなど構造化データのポリシーエンジン
  • KubernetesではCI時に、Conftestとの組み合わせで導入するケースが多い
  • CNCFのGraduatedプロジェクト

APIに送信するQueryと、Policyを参照して、評価したDecision(結果)を返す仕組みです。

Policy Decoupling

OPA公式ドキュメント

Conftest & Rego

Conftestは、バイナリファイルを所定のディレクトリに格納して、パスを通すことで簡単に利用できます。 Rego言語で定義したポリシーファイルと実際にチェックするファイルを所定のディレクトリに格納して、「$ conftest test <チェックするファイルまたはディレクトリのパス>」という形式でコマンドを実行して、定義したポリシーに違反していなければOK、NG場合はFAILを返します。

以下の例では、マニフェストファイルに「runAsNonRoot」が設定されていればOK、設定されていなければNGを返すポリシーをRegoで定義、実行しているものになります。

Conftest & Rego

Conftest GitHub

本ハンズオンでは、マニフェスト内のイメージタグに「latest」がある場合をNGとする定義をRegoで作成します。 以下は、マニフェスト内のイメージタグに「latest」が定義されていたら、NGとして「Cannot use latest tag !!」を返すというポリシーです。

package main

#イメージタグにlatestがある場合
deny[msg] {
  input.kind == "Deployment"
  image := input.spec.template.spec.containers[_].image
  endswith(image, "latest")
  msg := sprintf("latest tag: %s", [ image ])
}

#イメージタグに指定がない場合
deny[msg] {
  input.kind == "Deployment"
  image := input.spec.template.spec.containers[_].image
  not contains(image, ":")
  msg := sprintf("latest tag: %s", [ image ])
}

このRegoで定義したファイルを「policy」というディレクトリを作成して、格納します。

$ mkdir ./policy
$ vi ./policy/latest-tag-check.rego

Regoも使いこなすにはそれなりの学習コストが必要となります。本ハンズオンでは初歩的な定義ですが、詳細は以下公式ドキュメントをご参照ください。

Rego Official Documents

これまでの変更をConfigリポジトリにプッシュします。

$ git add .
$ git commit -m "Conftest and Rego"
$ git push origin main

プッシュ後に、CodeリポジトリからConfigリポジトリにプルリクエストが発行されたことをトリガーに、ポリシーチェックのCIが実行されて、OKとなります。マージするとこれまでと同じ処理の流れとなります。

Conftest NG Attempt

実際に、ConftestでNGを確認するには、以下の流れとなります。

  1. cicd-handson-2021-configディレクトリに移動
  2. goapp.yamlファイルのイメージタグをlatestに変更して保存
  3. Configリポジトリにプルリクエスト
  4. GitHub Actions CI処理の自動稼働
  5. NGの確認

cicd-handson-2021-configディレクトリに移動して、goapp.yamlファイルのイメージタグをlatestに変更して保存します。

$ cd cicd-handson-2021-config
$ vi ./manifests/goapp.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: goapp-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: goapp
  template:
    metadata:
      labels:
        app: goapp
    spec:
      containers:
      - name: goapp
        image: docker.pkg.github.com/<GITHUB_USER>/cicd-handson-2021-code/go-image:latest #変更箇所
        ports:
        - containerPort: 9090
      imagePullSecrets:
      - name: dockerconfigjson-github-com

Configリポジトリにプッシュします。

$ git branch feature/latest
$ git checkout feature/latest
$ git add manifests
$ git commit -m "Update tag latest"
$ git push origin feature/latest

GitHubのConfigリポジトリの画面からプルリクエストを作成します。 Compare & pull requestボタンをクリックします。

Compare & pull request

マージ先を <GitHub Account/cicd-handson-2021-config> リポジトリを指定します。

base:main

latest tagと入力して、Create pull requestボタンをクリックします。

Create pull request

プルリクエストが発行されたことをトリガーに、ポリシーチェックのCIが実行されて、NGとなります。
上部メニュー「Actions」を選択して、CIでエラーになっていることを確認します。
内容を確認する場合は、「Feature/latest」の部分をクリックします。

Actions NG1

「validation」をクリックします。

Actions NG2

「validate manifest-dir with custom policies」のプルダウンを開きます。 「return code: 1」になっていることを確認します。

Actions NG3

上部メニュー「Pull requests」をクリックして、対象のプルリクエストを選択します。

Actions NG3

[conftest] Validation Failed の「detail」をクリックして、failureの内容を確認します。

Actions NG3

Codeリポジトリ側のmain.ymlにおいては、イメージタグは自動で番号が付与されるようになっているので、latestが付与されることはありません。
本ハンズオンでは、確認のためにマニフェストファイルにlatestタグを付けて、直接Configリポジトリにプッシュ、プルリクエストというやり方を行いました。

以上で完了となります。
使用したリソースは忘れずに削除をしておいてください。


CD pipeline by Flux