Start Building for Free
CircleCI.comアカデミーブログコミュニティサポート

設定ファイルのポリシー管理機能の概要

クラウド
このページの内容

コンフィグファイルのポリシー管理機能を使って組織レベルのポリシーを作成し、設定要素が必須なのか、許可する、許可しないなどのルールとスコープを指定することができます。

はじめに

コンフィグファイルのポリシー管理機能により、CircleCI プロジェクトの設定ファイルを管理するポリシーを作成できます。 プロジェクトのコンフィグファイルが関連付けられたポリシーに定められたルールを遵守していない場合、最も厳しいケースでは、遵守するまでそのプロジェクトのパイプラインはトリガーできません。

CircleCI では、config.yml ファイルを使って CI/CD パイプラインをプロジェクトレベルで定義します。 この方法ではプロジェクトの拡大に伴い変化するニーズに合うように各パイプラインを作成できるため、開発や反復を迅速に行う際に便利です。 しかし、組織全体の規則やセキュリティポリシーを管理および制定することが困難な場合があります。 そんな場合に、設定ファイルのポリシー管理機能が役立ちます。

コンフィグファイルのポリシーについての判定は保存され、監査できます。 これにより、組織内で実行されているパイプラインの定義に関する有益なデータが得られます。

クイックスタート

VCS に接続した CircleCI アカウントを既にお持ちで、いますぐコンフィグファイルのポリシー管理機能を使用したい場合は、 ポリシーの作成ガイドをお読みください。

コンフィグファイルのポリシー管理機能の仕組み

設定ファイルのポリシー管理機能では、 Open Policy Agent (OPA) に基づく意思決定エンジンを使用します。 ポリシーは、OPA の定義に従い Rego クエリ言語で記述されます。 ルール違反があった場合は、パイプラインがトリガーされる際に表面化します。

ポリシーはローカルで作成し、CircleCI CLI を使って CircleCI にプッシュすることができます。 ポリシーは、ご自身の VCS 内のリポジトリに保存できます。 詳細については、 設定ファイルのポリシーの作成と管理のページを参照してください。

CircleCI では、OPA の出力結果に基づいてポリシーの適用に関する意思決定結果を生成します。 この結果は以下のようになります。

status:           PASS | SOFT_FAIL | HARD_FAIL | ERROR
reason:           string                                      (ステータスが ERROR の場合のみ表示)
enabled_rules:    Array<string>
soft_failures:    Array<{ rule: string, reason: string }>
hard_failures:    Array<{ rule: string, reason: string }>

意思決定の結果には、意思決定に使用されたルールと、検出されたルール違反 (soft_fail と hard_fail) の一覧が表示されます。

CLI を使用したコンフィグファイルのポリシー管理

CircleCI CLI を使って、プログラム上で組織のポリシーを管理することができます。 ポリシーの管理機能を実行するためのサブコマンドは、circleci policy コマンドにまとめられています。

設定ポリシーの管理において、CLI では現在以下のサブコマンドをサポートしています。

  • diff: ローカルポリシーバンドルとリモートポリシーバンドルとの相違点を示します。

  • fetch: ポリシーバンドルを (または 1 つのポリシーを名前に基づき) リモートからフェッチします。

  • push: ポリシーバンドルをプッシュ (アクティブ化) します。

    たとえば、以下のコマンドを実行すると、./policy_bundle_dir_path に保存されたポリシーバンドルがアクティブ化されます。

    circleci policy push ./policy_bundle_dir_path --owner-id <your-organization-ID>
  • settings- 必要に応じて設定ファイルのポリシー管理機能の設定を変更します。

    settings サブコマンドをフラグなしで呼び出した場合、現在の設定がフェッチされコンソールに出力されます。

    circleci policy settings --owner-id <your-organization-ID>

    以下のように出力されます。

    {
      "enabled": false
    }
  • test: ポリシーに対するテストを実行します。

    たとえば、以下のコマンドでは、policies ディレクトリにある定義済みテストがすべて実行されます。

    circleci policy test ./policies

    以下のように出力されます。

    ok    policies    0.001s
    
    3/3 tests passed (0.001s)

CircleCI ドメイン固有の言語を使った Rego ポリシーの記述

ポリシーは、OPA をサポートする専用の宣言型ポリシー言語である Rego で記述されます。 Rego の詳細については、 rego 言語に関するドキュメントを参照してください。

CircleCI が設定ファイルを判定するためには、ポリシーの評価結果を CircleCI が解釈できる必要があります。 そのため、ポリシーはこのページで説明されている CircleCI の仕様に合うように記述する必要があります。

パッケージと名前

すべてのポリシーが org パッケージに属し、ポリシー名を最初のルールとして宣言する必要があります。 ポリシーのすべての Rego ファイルには以下が含まれている必要があります。

package org

policy_name["unique_policy_name"]

policy_name は最大 80 文字の英数字の文字列です。 これは CircleCI において、ポリシーを名前で一意に識別するために使用されます (Kubernetes のリソース名と同様)。 ポリシー名は一意である必要があります。 1つの組織内で 2 つのポリシーに同じ名前をつけることはできません。

policy_name にはルールの一部を使い、rego key: policy_name["NAME"] として宣言する必要があります。

ルール

org パッケージと policy_name ルールを宣言すると、ポリシーをルールの一覧として定義できるようになります。 各ルールは 3 つのパートで構成されます。

  • 評価: 設定ファイルにポリシー違反がないかを評価

  • 措置: 違反している場合の措置

  • 有効化: 措置を有効にするかどうかを決定

ポリシーを作成する場合には、このフォーマットに従っていれば、CircleCI でのポリシー評価出力の解析に影響を与えることなくカスタムヘルパー関数を作成できます。 ただし、カスタムヘルパー関数を作成する代わりに、ポリシーに data.circleci.config をインポートして CircleCI 製のヘルパーを利用することも可能です。 詳細については、 設定ファイルのポリシーのリファレンスを参照してください。

ポリシーはすべて input 変数を使って設定データにアクセスできます。 input は評価されるプロジェクトの設定です。 この input は CircleCI の設定ファイルの内容と一致するので、jobsworkflows などの使用可能な任意の設定要素に希望の評価結果を適用するルールを記述することができます。

input.workflows     # an array of nested structures mirroring workflows in the CircleCI config
input.jobs          # an array of nested structures mirroring jobs in the CircleCI config

ルールの定義

OPA では、ルールよってあらゆるタイプの出力を生成できます。 CircleCI では、違反の対象となるルールには、以下のタイプの出力が必要です。

  • 文字列

  • 文字列配列

  • 文字列から文字列のマップ

これは、ルール違反があった際に、開発者や SecOps がそれに基づき対応するためのエラーメッセージが生成される必要があるためです。 別のタイプの出力を生成するヘルパールールを定義することもできますが、CircleCI が判定時に考慮するルールは、上記の出力タイプでなければなりません。 詳細については、下記の 有効化 のセクションをご覧ください。

評価

設定ファイルが規定されたポリシーに違反した場合に、意思決定エンジンがどのように判定するかを説明します。 評価では、ルールの名前と ID を定義し、条件をチェックして、違反について記載するユーザーフレンドリーな文字列を返します。 ルールの評価には、ルール名オプションのルール ID が含まれます。 ルール名は、ルールの評価結果を有効化し、措置を設定するために使用されます。

RULE_NAME = reason {
  ... # some comparison
  reason := "..."
}
RULE_NAME[RULE_ID] = reason {
  ... # some comparison
  reason := "..."
}

下記は、設定に少なくとも 1 つのワークフローが含まれる設定をチェックするシンプルな評価の例です。

contains_workflows = reason {
    count(input.workflows) > 0
    reason := "config must contain at least one workflow"
}

ルール ID は 1 つのルールについて複数回の違反があった場合に識別するために使用されます。 たとえば、1 つの設定ファイルで非公式の Docker イメージを複数使用している場合、use_official_docker_image ルールに複数回違反することになります。 ルール ID は複数回の違反が予測される場合のみ使用してください。 場合によっては、ルールを遵守しているかどうかだけを知りたい場合もあります。 その場合、ルール ID は不要です。

use_official_docker_image[image] = reason {
  some image in docker_images   # docker_images are parsed below
  not startswith(image, "circleci")
  not startswith(image, "cimg")
  reason := sprintf("%s is not an approved Docker image", [image])
}

# helper to parse docker images from the config
docker_images := {image | walk(input, [path, value])  # walk the entire config tree
                          path[_] == "docker"         # find any settings that match 'docker'
                          image := value[_].image}    # grab the images from that section
措置

このポリシーの管理機能では、ルールの措置レベルを設定できます。

ENFORCEMENT_STATUS["RULE_NAME"]

設定可能なレベルは、以下の 2 つのレベルです。

  • hard_fail: policy-service が設定ファイルにおいて hard_fail と設定されたルールに対する違反を検出した場合、パイプラインはトリガーされません。

  • soft_fail: policy-service が設定ファイルにおいて soft_fail と設定されたルールに対する違反を検出した場合、パイプラインはトリガーされますが、そのルール違反は policy-service の判定ログに記録されます。

use_official_docker_image ルールを hard_fail に設定した例:

hard_fail["use_official_docker_image"]
有効化

ポリシー違反を審査するためにはルールを有効化する必要があります。 有効化されていないルールは、CircleCI 違反出力形式に合致する必要はなく、他のルールのヘルパーとして使用できます。

enable_rule["RULE_NAME"]

ルールを有効化するには、そのルールを enable_rule オブジェクトにキーとして追加します。 たとえば、use_official_docker_image ルールを有効化する場合、以下を使用します。

enable_rule["use_official_docker_image"]

パイプラインのメタデータの使用

CircleCI 設定ファイルのポリシーを記述する場合、多くの場合プロジェクトやブランチごとに動作が若干異なるポリシーにすることが推奨されます。 それには data.meta Rego プロパティーを使用します。

ポリシーがトリガーされたパイプラインのコンテキストで評価されると、data.meta において以下の 3 つのプロパティーが使用できるようになります。

project_id    (CircleCI Project UUID)
branch        (string)
build_number  (number)

このメタデータは、ルールのアクティブ化/非アクティブ化、評価結果の変更、およびルール定義自体の一部として使用できます。

以下は 1 つのプロジェクトに対してのみルールを制定し、main ブランチ上でのみ hard_fail とするポリシーのサンプルです。

package org

policy_name["example"]

# specific project UUID
# use care to avoid naming collisions as assignments are global across the entire policy bundle
sample_project_id := "c2af7012-076a-11ed-84e6-f7fa45ad0fd1"

# this rule is enabled only if the body is evaluates to true
enable_rule["custom_rule"] { data.meta.project_id == sample_project_id }

# "custom_rule" evaluates to a hard_failure condition only if run in the context of branch main
hard_fail["custom_rule"] { data.meta.vcs.branch == "main" }

以下は、信頼できないオリジンからのプルリクエストビルドをブロックするポリシーの例です。

package org

import future.keywords

policy_name["forked_pull_requests"]

# this rule is enabled only if the body evaluates to true (origin_repository_url and target_repository_url will be different in case of a forked pull request)
enable_rule["check_forked_builds"] {
	data.meta.vcs.origin_repository_url != data.meta.vcs.target_repository_url
}

# enable hard failure
hard_fail["check_forked_builds"]

check_forked_builds = reason {
	not from_trusted_origin(data.meta.vcs.origin_repository_url)
	reason := sprintf("pipeline triggered from untrusted origin: %s", [data.meta.vcs.origin_repository_url])
}

from_trusted_origin(origin) {
	some trusted_origin in {
		"https://github.com/trusted_org/",
		"https://bitbucket.org/trusted_org/",
	}

	startswith(origin, trusted_origin)
}

ポリシーのテスト

新しいポリシーを使用する場合、そのポリシーがどのように適用され、どのような意思決定結果が生成されるのかを事前に把握して、不安なくデプロイできなくてはなりません。 そのためのコマンドとして、circleci policy test を利用できます。 この test サブコマンドは、golang や opa のテストコマンドを参考にしています。 テストの準備の詳細については、 設定ファイルのポリシーのテストを参照してください。

サンプルポリシー

以下に、use_official_docker_image という 1 つのルールが設定されたサンプルポリシーの全体像を示します。このルールは、設定ファイル内に含まれる全 Docker イメージの接頭辞が circleci または cimg であるかをチェックします。 設定ファイル内のすべての docker_images を見つけるヘルパーコードを使用しています。 use_official_docker_image の評価結果を hard_fail に設定し、このルールを有効化しています。

また、このサンプルでは future.keywords をインポートしています。詳細については、 OPA のドキュメント (英語) を参照してください。

package org

import future.keywords

policy_name["example"]

use_official_docker_image[image] = reason {
  some image in docker_images   # docker_images are parsed below
  not startswith(image, "circleci")
  not startswith(image, "cimg")
  reason := sprintf("%s is not an approved Docker image", [image])
}

# helper to parse docker images from the config
docker_images := {image | walk(input, [path, value])  # walk the entire config tree
                          path[_] == "docker"         # find any settings that match 'docker'
                          image := value[_].image}    # grab the images from that section

hard_fail["use_official_docker_image"]

enable_rule["use_official_docker_image"]

ドキュメントの改善にご協力ください

このガイドは、CircleCI の他のドキュメントと同様にオープンソースであり、 GitHub でご利用いただけます。 ご協力いただき、ありがとうございます。

サポートが必要ですか

CircleCI のサポートエンジニアによる、サービスに関する問題、請求およびアカウントについての質問への対応、設定の構築に関する問題解決のサポートを行っています。 サポートチケットを送信して、CircleCI のサポートエンジニアにお問い合わせください。日本語でお問い合わせいただけます。

または、 サポートサイト から、サポート記事やコミュニティフォーラム、トレーニングリソースをご覧いただけます。