TerraformにおけるOPAのユースケース

メディア統括本部 サービスリライアビリティグループ(SRG)の石川雲(@ishikawa_kumo)です。
#SRG(Service Reliability Group)は、主に弊社メディアサービスのインフラ周りを横断的にサポートしており、既存サービスの改善や新規立ち上げ、OSS貢献などを行っているグループです。
本記事は、過去Qiitaに投稿した「TerraformにおけるOPAのユースケース」記事の増強版です。
 

概要


Open Policy Agent(OPA)は、JSONやYAMLベースのInfrastructure as Code(IaC)管理において、近年広く用いられるようになっています。特に、Kubernetesのマニフェストに対するOPAとGateKeeperの導入が標準化されつつあります。
一方で、Terraformのような、複雑なクラウドインフラの記述に長けたツールとの統合は、まだ挑戦的であり、実際の連携例は少ない状況です。Terraform CloudやStyraとの組み合わせでの利用事例は存在しますが、純粋なTerraform環境(例えば、バックエンドがS3の場合)でのOPAの活用は、まだそれほど多くはありません。
この記事では、Terraform環境でのOPAのユースケースとその実践的な利用方法に焦点を当てていきます。

OPAとRegoについて


OPAは、Regoポリシーを集中的に管理するエンジンです。JSON形式の入力データに対して、複数のシステム間で一貫性のあるポリシーを適用することが可能です。RegoはOPA用のドメイン固有言語であり、データに対するポリシーを表現するために使用されます。
Regoは宣言型プログラミング言語の一種として、複雑な論理処理や動的なJSON構造の処理は難易度が高いです。また、Regoポリシーの開発において、手続型プログラミング言語と顕著的な違いがあり、数理論理学の角度からポリシーを書く必要がたまにあります。

既存のRegoポリシーと関連ツール

開発体制が整っていない状況でRegoの開発に着手すると、メンテナンスの面で大きな負担を背負うことになる可能性があります。できる限り、コミュニティによって既に作成されたRegoを利用することを推奨します。
  • Rego Library OPAコミュニティで共有されているポリシーの例
Regoのベストプラクティスについては、OPAの開発会社が提供する内容を参照すると良いでしょう。
また、優れたLinterであるregalも利用可能ですので、ぜひ活用してみてください。

Rego の注意点

下記では、Regoポリシー開発でよく発生する問題と推奨をまとめてみました。
  1. 変数に再代入できない
    1. 一度値を割り当てた変数へ新しい値の代入ができません。例えば以下のRegoでは、 という変数を再代入しようとすると、ルール自体はevalされません。
      サンプル
  1. Safetyの原則
    1. 要するに、以下の赤枠の部分に出現する全ての変数は、明確的な「非否定的」な定義が必要です。
      例えば、以下の では、直感的に valueが0ではないkeyを取り出しているように読めますが、クエリ言語や論理プログラミングでは unsafeとされています。
      サンプル
      Regoのルールブロックでは、単純にまたは として評価しているため、論理上確実に真偽値が存在しないといけません。
      しかし、辞書が存在しない場合、この条件は直接的な値の比較ではなく、存在しないキーに関する扱いに依存します。論理プログラミングやデータベースのクエリでは、通常、存在しないキーへのアクセスはエラーを引き起こすか無視されるかのどちらかです。
      Regoでは、条件は単純にまたはとして評価されない場合、エラーを引き起こされます。
      確実に真偽値が存在するよう、以下のように修正すればエラーが消えます。という条件は、が辞書に存在し、かつその値が0でないことを明示的にチェックします。これにより、に関する安全性の原則を満たすと同時に、期待される挙動を保証します。辞書が存在しない場合、この条件は偽と評価されます。
  1. デフォルト値の設定
    1. デフォルト許可、デフォルト拒否、デフォルト許可と拒否のオーバーライドのスタイルを利用し、不用意なの結果になることを減らせます。

Inputの選択

OPAの検証はJSONベースなので、Terraformの各検証対象に対し、JSONとして出力する必要があります。
Terraformの検証対象は概ね以下の種類があります。
  • state JSON
    • 、定期実行ジョブで現時点のインフラ構成を検証する用途です
  • plan JSON
    • のJSON出力、検証目的によって利用する部分も違います。
      詳細は以下のドキュメントをご参考ください。
  • terraform HCL
    • Terraformのソースコードで使われるHCL言語は、JSON に由来する言語であるため、などの変換機能を持つツールを経由してOPAで評価することができます。また、Conftest がなくても、コマンドラインツールを使用してHCLを JSON に一度変換してからOPAに渡すことも一つの方法です。

ポリシー評価エンジンの選択

tfsec・trivy

tfsec cliは、Rego で書かれたカスタムポリシーを導入する機能を持っています。
例えば、以下のS3に対し、簡単なregoを導入すると、以下の結果が得られます。
Terraform
Rego
rego inputにあるは、通常のHCLからパースされたJSONとは異なり、tfsecによって処理可能なフォーマットに変換されています。なお、tfsecがサポートしているrego inputの種類は で確認できます。
2023年2月以降、tfsecがtrivyプロジェクトの一部になったため、将来的には直接trivyを使ったほうが良いでしょう。ドキュメントによると、trivyでもcustom policyに対応しており、より整備されたフォーマットのmetadataで定義できます。
ただし、2024年2月時点の では、trivy + regoカスタムポリシーのドキュメントと記述例は乱雑状態になっており、過去のフォーマットや既にサポートしていないポリシーなども混在しています。また、terraform awsに関するinputの種類も整備されておらず、trace方式のデバッグのみ対応しているなど、諸事情により現段階での導入は困難だと考えられます。

tflint

tflintは、Custom Plugin機能を備えています。Go言語による開発が必要です。以下のリポジトリは、OPA Rego を Go プラグイン経由で評価するためのプラグインです。
現段階のでは、少しの工夫を加えることで自動化にも組み込むことができます。
事前準備
  1. の設定
    1. policyの準備
      1. READMEではデフォルト設定の が書かれているが、実際Recursiveモードでスキャンする際に参照されませんので、デフォルト設定以外のところに置いても、実行する際にいずれ手動で指定する必要があります。
        なので、と並列でフォルダに置くことがおすすめです。
    1. 全体のディレクトリ構成
      実行
      実行するにあたって、以下の環境変数は要注意です。
        • policyファイル
        • OPA トレーシング
        • OPAテストモード
        • TFLINT自身のログ、OPA Printのデバッグも利用可能

      conftest

      conftestは、直接 HCL を読み込むことができるなどの利点があり、準備と設定もtfsecやtflintより簡単です。
      また、conftestは直接Githubで公開されているポリシーを直接利用することが可能です。
      ただし、現時点で Conftest はregoのtraceモードのみに対応しており、OPA ポリシーの開発が難しい可能性があります。

      Terraform OPA連携のユースケース


      組織固有ポリシーの定義と適用

      組織固有のポリシー、例えば統計用のタグ指定やマルチ環境対応のフォーマット指定、特定リソースへのIAM割り当てなどは、OPAを用いて柔軟に設定できます。これらのポリシーは組織の実際の要件に沿って慎重に検討する必要があります。
      例えば、以下のような例があります。
      全てのVariableは、Terrafrom Workspaceごとに区別できるmap構成
      サンプル

      整合性チェック

      Providerがまだ提供していないバリデーションを補完する目的で、細かい値の制御を検証する用途です。 簡単な値チェックなら、ブロックで簡単にできますが、複雑条件の制御はValidationブロックだけでは難しいので、この場合Regoを使ってもいいと考えています。
      もちろん、ほとんどの場合、変数構成の再設計とValidationブロックやpre/postconditionブロックなど組み合わせによって、解決できると思います。Regoを使って、複雑条件の制御を書くのに向いています。
      以下のような例があります。
      二つVariableのお互いに影響する条件設定
      サンプル
      その他には、目で確認していたロジックもRegoで書くことができます。
      • AWS Network FirewallのSubnetとRouteTable設定が正しいかどうか
      • AWS WAFのRuleは規定の必須Ruleを実装しているかどうか

      自動化フローの一環

      JSON Parserとして使うというのは酷いかもしれませんが、企業固有のポリシーの実施に加えて、OPAをJSON Parserとして活用することは有効です。
      ただし、現時点でOPAはデバッグやエラーメッセージ以外の目的での出力使用はまだ限定的ですので、CIフローの中で特定のコンプライアンスにおけるポリシーとルールを評価し、真偽値(True/False)の結果のみを利用することをお勧めします。
      以下のような例があります。
      サンプル
      リソースが削除される予定である場合、このポリシーは適切な警告メッセージを生成し、ユーザーに対してその操作が意図的であるかどうかを再確認するよう促します。

      終わりに


      OPAとRego言語の統合は、Terraformによるクラウドインフラの管理を効率的にする大きな潜在能力を持っています。しかし、Regoの開発には相応の労力が必要であり、これがTerraform環境におけるOPAの導入の障壁の一つとなっています。この記事を通じて、TerraformとOPAを統合することの重要性と、そのためのベストプラクティスを理解いただけたことでしょう。現在、TerraformとOPAの実際の連携事例はまだ少ないですが、この分野の将来的な発展が非常に期待されています。
       
      SRG では一緒に働く仲間を募集しています。 ご興味ありましたらぜひこちらからご連絡ください。
       
      SRG では最近出たホットなIT技術や書籍などについてワイワイ雑談するポッドキャストを運営しています。ぜひ、作業のお供に聞いていただければ幸いです。
      このエントリーをはてなブックマークに追加