Skip to main content

OPAとRegoでポリシー・アズ・コード(PaC)を実現

blog feature snyk iac magenta

2022年1月19日

0 分で読めます

Cambridge Dictionaryでは、ポリシーを「特定の状況で何をすべきかについて、人々の集団、企業組織、政府、政党などが公式に合意した考え方や計画」と定義しています。ソフトウェア開発においても、ポリシーの作成、設定、デプロイ、利用方法について、組織内で定めたルールがあるでしょう。ソフトウェアポリシーの例をいくつか挙げます。

アプリケーションポリシー

  • 特定のWebサービスのコンテキストには、社内ユーザーのみがアクセスできる。

  • 地域別の機能は、同じ地域のIPアドレスを持つユーザーからのリクエストに対してのみ表示する。

  • 一定額を超える取引は、管理職のユーザーに限り許可する。

ビルドとデプロイのポリシー

  • オープンソースのアプリケーションライブラリはすべて、承認済みライセンスのいずれかを使用しなければならない。

  • コンテナイメージはすべて、指定されたレジストリから取得しなければならない。

  • Kubernetes PodをPrivilegedモードで実行してはならない。

  • ServiceAccountのデフォルトトークンをコンテナに自動マウントしてはならない。

ポリシー・アズ・コード(PaC)とは、高水準の宣言型言語を用いてポリシーをコードとして定義するプロセスです。ポリシーの適用を自動化し、一元管理できるようになります。分散化が進み、多様な言語やプラットフォームを利用するアプリケーションサービス間でロジックを重複させる必要も減らせます。

この記事では、Open Policy Agent(OPA)とそのルール言語Regoを取り上げます。これらは、自社アプリケーションでのPaCの取り組みを効率化するとともに、Kubernetes上のコンテナ化されたワークロードにポリシーを適用するために活用できます。

異なるサービス間でポリシー定義を統一する

アプリケーションのポリシー適用は、多くの場合、コードに直接実装されます。現在の分散システムでは、同じロジックが重複することがあります。異なるサービスを別々のチームが開発していたり、異なるテクノロジーを使っていたりすると、この問題はさらに大きくなります。

組織内のすべてのチームが、使用言語やフレームワークを問わず利用できる、標準化されたポリシー定義と適用ツールを整備することが重要です。ポリシー定義を統一すれば、関係者全員にとって実装がシンプルで柔軟になり、コンプライアンスのガバナンスも容易になります。

ビルドとデプロイにおける事後対応型からプロアクティブなポリシー適用へ

ビルドとデプロイのポリシールールは、多くの場合、手動のコードレビュー、静的解析(CI/CDパイプラインへの自動化が望まれます)、あるいはポリシー違反に対する懲戒処分の可能性を組み合わせて適用されます。こうした手法は事後対応型であり、何らかの監査が行われた時点でポリシー違反を知らせます。これでも機能する場合はありますが、ポリシーの策定者と、ポリシールールの存在を十分に認識していない開発者との間に、対立関係を生むことが少なくありません。

ポリシーを開発者のワークフローに組み込み、ビルドプロセスの一部やデプロイのゲートとして適用すれば、後工程の監査や手動レビューに頼るのではなく、違反が発生した時点で阻止できます。

異なる環境間でポリシーの適用を統一する

ポリシールールを単一の共有プラットフォームに統合できれば、すべての環境に一貫して適用できるようになります。たとえば、開発用のサンドボックスKubernetesクラスターでは何でも自由にデプロイできる一方、本番クラスターには複数の制限がある場合、開発者はSDLCの後半になるまで違反に気付かない可能性があります。しかし、すべてのクラスターで同じルールセットを共有すれば、初期のユニットテストで違反が発見されるため、ソース管理にコミットされる可能性は大幅に低くなります。

Open Policy Agent(OPA)

Open Policy Agentは、通常OPAと略され、「オーパ」と発音される、CNCF卒業プロジェクトのオープンソース汎用ポリシーエンジンです。アプリケーションポリシー、特に分散型マイクロサービスアーキテクチャで広く利用されているほか、Kubernetes APIのアドミッションコントローラーとしても使われ、OPA Gatekeeperプロジェクトを通じて統合されることもよくあります。

アプリケーションはポリシー検証をOPAに委任できるため、ロジックをコードベースに密結合させる必要がなくなります。実際には、OPAプロセスをアプリケーションサービスと並行して起動し、アプリケーションが通信できるREST APIを公開する構成がよく使われます。Kubernetesへのデプロイでは、通常、サービスコンテナと同じPod内でサイドカーコンテナとして実行します。これにより、遅延を極めて低く抑えた「localhost」接続が可能になりますが、外部サービスとして実行することもできます。OPAをアプリケーションに組み込む方法はほかにもあり、この記事の執筆時点では、Go API、WebAssembly、Goアプリケーション内にOPAを埋め込むためのSDKが利用できます。

OPAでは、Regoという言語を使い、一連のルールとしてポリシーを記述します。

Rego:OPAのポリシールール言語

Regoは、JSONのような構造化ドキュメントに対するルールの実装を目的に設計された高水準の宣言型言語です。Regoルールの作成方法を詳しく解説することはこの記事の範囲外ですが、OPAとRegoの開発元による公式ドキュメントと、Styraによる優れた学習コースをぜひご覧ください。

Regoの基本

Regoはさまざまな方法で構造化データドキュメントを扱えますが、最も一般的なのは、呼び出し元のプロセスがドキュメント(多くの場合JSONまたはYAML形式)をinputとして渡す方法です。その後、入力ドキュメントの要素と式を比較してルールを適用します。

たとえば、入力のimage値が「:latest」で終わらない限りtrueを返す、Kubernetes Pod用のバリデーターポリシーを考えてみましょう。このポリシーをRegoで簡単に実装すると、次のようになります。

package kubernetes.validating.images

import future.keywords.in

default allow = false

allow {
    input.kind == "Pod"
some container in input.spec.containers
not endswith(container.image, ":latest")
}

次のJSONをこのポリシーで評価すると、イメージの末尾が「:latest」なので、{ “allow”: false }という応答が返されます。

{
    "kind": "Pod",
    "apiVersion": "v1",
    "metadata": {
        "name": "mypod",
        "labels": { "run": "mypod" }
    },
    "spec": {
        "containers": [
            {
                "name": "mypod",
                "image": "registry.mycorp.com/team-alpha/myapp:v1",
            }
        ]
    }
}

Regoの例を読み解く

上記の例にあるRegoコードを順に見ていきましょう。

package kubernetes.validating.images

ここでは、ルールが属するpackageを宣言しています。これはほかの言語のパッケージと同様のもので、関連するルールを同じ名前空間にまとめるために使います。

import future.keywords.in

importキーワードは、future.keyworksパッケージからinルールをRegoパーサーに読み込ませ、このポリシーのスコープ内で単にinと記述して参照できるようにします。

default allow = false

ここでは、ポリシー内のほかの代入式で値が設定されない場合に、allowのdefault値を「false」と定義しています。

allow {
    input.kind == "Pod"
    some container in input.spec.containers
    not endswith(container.image, ":latest")
}

ここがルールロジックの大部分です。実行時、allowには{ }内の内容を評価した結果が代入されます。中の式はすべて暗黙的な「AND」で評価されるため、allowを「true」にするには、すべての式が「true」と評価される必要があります。

この3行は、「input.kindの値が「Pod」であり、input.specにコンテナが1つ以上ある限り、いずれかのコンテナのimageフィールドが「:latest」で終わる場合を除いて「true」を返す」と解釈できます。

Rego Playground

OPAプロジェクトでは、The Rego PlaygroundというオンラインのRegoエディター環境を提供しています。ルールを試したり、任意の入力ドキュメントに対して実行したりできます。ルールのアイデアをインタラクティブに試し、その結果を誰とでも共有できる便利なツールです。

Kubernetesイメージ検証ポリシー、PodのJSON入力、allow: trueを示す出力が表示されたRego Playgroundのインターフェース

上記のRegoコードと入力ドキュメントは、こちらのRego Playgroundの例で確認できます。別のタブで開いて実行し、いろいろ試してみてください。

Snyk IaCとRegoを使ったカスタムポリシーの作成

Snyk Infrastructure as Code (Snyk IaC)は、ポリシースキャンにOPAを活用しています。簡単なコマンドをいくつか実行するだけで、独自のポリシーをスキャンに追加できます。始めるには、Snyk IaCのドキュメントと、記事「SnykでカスタムIaCルールを開発する」をご覧ください。

Snykの無料アカウントを作成すると、セキュリティチェック、ポリシーのガードレール、開発者にわかりやすい修正ガイダンスをワークフローにシームレスに組み込み、IaCの設定ミスを特定して修正できます。

ソースコードの段階からインフラを保護

Snykはワークフロー内のIaCセキュリティとコンプライアンスを自動化し、構成ドリフトや不足しているリソースを検出します。

さらに学ぶためのリソース

OPAとRegoの概要や、活用方法について理解できたところで、ソフトウェア開発に役立てるさまざまな方法をぜひ探してみてください。

最後までお読みいただきありがとうございます。ポリシー適用の自動化をぜひ楽しんでください!