RegulaとOpen Policy Agentを使ってTerraform内のAWS AMI IDを確認する
2021年10月7日
0 分で読めます編集者注
このブログ記事は、もともとfugue.coに掲載されていました。Fugueは2022年にSnykの一員となり、Snyk IaCの重要な構成要素となっています。
先週、Fugue IaCを発表しました。クラウドエンジニアリングチームは、同じポリシーを使ってInfrastructure as Code(IaC)とクラウドのランタイム環境を保護できます。IaCをローカルでチェックするために、FugueはRegulaを開発しました。これはOpen Policy Agent(OPA)を基盤とするオープンソースツールです。
Regulaは、Fugueの有無にかかわらず使用できます。TerraformやCloudFormationのInfrastructure as Code(IaC)、Kubernetesマニフェストをチェックするための、すぐに使える数百ものルールが用意されています。これらのルールはCIS Benchmarksに対応しており、さまざまなセキュリティ上の脆弱性をカバーします。
一方、Amazon EC2インスタンスでは承認済みのAMIを使用することを必須にするなど、組織固有のポリシーを適用したい場合もあります。そのような場合は、OPAのRego言語を使ってカスタムルールを記述し、RegulaでIaCに適用できます。これにより、IaCで承認されていないAMIを指定すると、Regulaのチェックは失敗します。
この記事では、次の内容を紹介します。
Terraformで宣言されたAWS EC2 AMIをチェックするカスタムルールを作成し、Regoコードを1行ずつ解説します。
オープンソースツールのRegulaを使って、準拠していないTerraformファイルに対してルールをテストします。
準拠していないTerraformを修正します。
この記事ではRegulaを使ってTerraform HCLをチェックしますが、同じカスタムルールをFugue SaaSで使い、クラウドのランタイムリソースをチェックすることもできます。これは、IaCとランタイムで同じルールを使用できるFugueのUnified Policy Engineによって実現します。
コードはすべてこちらのGitHub gistで確認できます。
それでは始めましょう。
始める前に
コードファイルをダウンロードする
GitHub gistで「Download ZIP」ボタンを選択し、ファイルを展開します。ファイルは2つあります。
approved_ami.rego – Regoで記述されたカスタムルール
ami.tf – 準拠しているEC2インスタンスと準拠していないEC2インスタンスを1つずつ宣言したTerraform HCLファイル
Regulaをインストールする
次に、まだの場合はRegulaをインストールします。Homebrewを使う場合は、ターミナルで次のコマンドを実行してください。
また、お使いのプラットフォーム向けのビルド済みバイナリをインストールするか、DockerでRegulaを実行することもできます。
カスタムルールを記述する
まず、作成するルールの種類を決めましょう。Regulaには2種類のルールがあります。シンプルルールと高度なルールです。シンプルルールは、単一のリソースタイプをチェックする場合に便利です。複数のリソースにまたがる複雑なロジックや、リソースの欠落をチェックする場合は、高度なルールが適しています。
今回はTerraformのリソースタイプaws_instanceを1つだけチェックするため、シンプルルールを作成します。
パッケージ宣言
まずは基本から始めましょう。Regulaのルールにはすべて、rules.で始まり、短い識別子で終わるパッケージ宣言が必要です(4行目)。
メタデータ
必要に応じてメタデータを追加できます(6~18行目)。
必須ではありませんが、Regulaのレポート出力をさらにわかりやすくできます。
リソースタイプ
次に、チェック対象のTerraformリソースタイプを指定します(20行目)。
この構文は、入力が単一のAWS EC2インスタンスであることを意味します。RegulaはTerraformにルールを適用する際、インスタンスを1つずつ評価します。
承認済みAMIのセット
ここでは簡単にするため、組織が次の2つのAMI IDを承認しているとします。
ami-09e67e426f25ce0d7
ami-03d5c68bab01f3496
(参考までに、これらはそれぞれus-east-1とus-west-2におけるUbuntu Server 20.04 LTS HVM、SSD Volume TypeのIDです。)
次に、承認済みAMI IDを含むセットを作成します。名前はapproved_amisとします(22~26行目)。
denyルール
最後に、denyルールを記述します。ここに主要なロジックを定義します。denyルールでは、リソースのチェックが失敗する条件を指定します。
今回は少し工夫して、Regulaのチェックに失敗したインスタンスの未承認AMI IDを示すカスタムエラーメッセージを返すようにします。
denyルールでは、評価中のインスタンスのAMI IDが承認済みセットに含まれているかどうかを確認します。含まれていない場合は、そのリソースに対するエラーメッセージを返します(つまり、ルールの結果を失敗にします)。denyは28~31行目で定義します。
ロジックを詳しく見てみましょう。
input.amiは、入力ドキュメント(Terraform HCLファイル、より具体的にはRegulaが内部で変換したJSON表現)に含まれる各EC2インスタンスのami属性を表します。
not approved_amis[input.ami]は、現在のインスタンスのami属性がセットのメンバーではない場合にtrueと評価されます。
つまり、denyルールは「input.amiがapproved_amisに含まれていない場合、Regulaのチェックは失敗し、エラーメッセージを返す」と指定しています。
エラーメッセージは次の行で定義します。
ここではRegoの組み込み関数sprintfを使って、評価中のリソースのamiを出力します。
これでカスタムルールは完成です。全体はこちらで確認できます。それではRegulaを実際に使ってみましょう。
Regulaでカスタムルールを実行する
それでは、シンプルなTerraformファイルでルールをテストしてみましょう。GitHub gistにあるTerraform HCLでは、EC2インスタンスを2つ定義しています。1つは承認済みAMI IDami-09e67e426f25ce0d7を使う「良い」インスタンス、もう1つは、まったく怪しくないAMI IDami-totallylegitamiidを使う「悪い」インスタンスです。
Regulaを実行する
ターミナルで、コードファイルがあるディレクトリにcdで移動し、次のコマンドを実行します。
このコマンドはTerraformファイルに対してカスタムルールを実行します。--user-onlyフラグは、カスタムルールだけを適用するよう指定します。この記事では、Regulaの組み込みルールライブラリを対象から除外しています。(ただし、regula runを実行するとデフォルトで適用される組み込みルールの使用をおすすめします。)
次のような出力が表示されます。

ご覧のとおり、Terraformファイルはルールに違反し、ami-totallylegitamiid is not an approved AMI IDというメッセージが表示されました。これは、カスタムルールが機能したことを意味します。Regulaは、aws_instance.badインスタンス(13行目、1列目)に承認済みAMI IDが設定されていないことを示しました。
詳細なレポートを見る
詳細を確認するため、JSON形式のレポート全体を見てみましょう。
ここでは、すべてのルール結果を含む出力全体を確認できます。下の例では、aws_instance.badの結果が再びFAILである一方、aws_instance.goodのルール結果はPASSになっています。
先ほどルールで定義した残りのメタデータも確認できます。
Terraformを修正する
Terraformを準拠させるには、ami.tfを編集し、ami-totallylegitamiidをami-09e67e426f25ce0d7に置き換えてから、Regulaをもう一度実行します。今度はデフォルトのテキスト形式を使います。
次のような出力が表示されます。
成功です。Regulaで確認したとおり、承認済みAMIのみを使用することでTerraform IaCを保護できました。
さらに詳しく
この記事では、Regoでカスタムルールを作成し、Regulaを使ってTerraform HCLファイルに対してチェックを実行し、Terraformを準拠させました。
Regulaについて詳しく知りたい方は、Regulaのドキュメントサイトをご覧ください。次のリソースも参考になります。
開発者のために設計されたIaCセキュリティ
Snykは、統合されたポリシー・アズ・コードエンジンにより、SDLCからクラウドでの実行時までInfrastructure as Codeを保護します。すべてのチームが安全に開発、デプロイ、運用できるよう支援します。



