Skip to main content

RegulaとOpen Policy Agentを使ってTerraform内のAWS AMI IDを確認する

著者
blog hero iac drift purple

2021年10月7日

0 分で読めます

先週、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を使う場合は、ターミナルで次のコマンドを実行してください。

brew tap fugue/regula
brew install regula

また、お使いのプラットフォーム向けのビルド済みバイナリをインストールするか、DockerでRegulaを実行することもできます。

カスタムルールを記述する

まず、作成するルールの種類を決めましょう。Regulaには2種類のルールがあります。シンプルルールと高度なルールです。シンプルルールは、単一のリソースタイプをチェックする場合に便利です。複数のリソースにまたがる複雑なロジックや、リソースの欠落をチェックする場合は、高度なルールが適しています。

今回はTerraformのリソースタイプaws_instanceを1つだけチェックするため、シンプルルールを作成します。

パッケージ宣言

まずは基本から始めましょう。Regulaのルールにはすべて、rules.で始まり、短い識別子で終わるパッケージ宣言が必要です(4行目)。

package rules.approved_ami

メタデータ

必要に応じてメタデータを追加できます(6~18行目)。

__rego__metadoc__ := {
  "id": "CUSTOM_0002",
  "title": "AWS EC2 instances must use approved AMIs",
  "description": "Per company policy, EC2 instances may only use AMI IDs from a pre-approved list",
  "custom": {
    "controls": {
      "CORPORATE-POLICY": [
        "CORPORATE-POLICY_1.2"
      ]
    },
    "severity": "High"
  }
}

必須ではありませんが、Regulaのレポート出力をさらにわかりやすくできます。

リソースタイプ

次に、チェック対象のTerraformリソースタイプを指定します(20行目)。

resource_type = "aws_instance"

この構文は、入力が単一の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行目)。

approved_amis = {
  # Ubuntu Server 20.04 LTS (HVM), SSD Volume Type
  "ami-09e67e426f25ce0d7", # us-east-1
  "ami-03d5c68bab01f3496" # us-west-2 
}

denyルール

最後に、denyルールを記述します。ここに主要なロジックを定義します。denyルールでは、リソースのチェックが失敗する条件を指定します。

今回は少し工夫して、Regulaのチェックに失敗したインスタンスの未承認AMI IDを示すカスタムエラーメッセージを返すようにします。

denyルールでは、評価中のインスタンスのAMI IDが承認済みセットに含まれているかどうかを確認します。含まれていない場合は、そのリソースに対するエラーメッセージを返します(つまり、ルールの結果を失敗にします)。denyは28~31行目で定義します。

deny[msg] {
  not approved_amis[input.ami]
  msg = sprintf("%s is not an approved AMI ID", [input.ami])
}

ロジックを詳しく見てみましょう。

not approved_amis[input.ami]

input.amiは、入力ドキュメント(Terraform HCLファイル、より具体的にはRegulaが内部で変換したJSON表現)に含まれる各EC2インスタンスのami属性を表します。

not approved_amis[input.ami]は、現在のインスタンスのami属性がセットのメンバーではない場合にtrueと評価されます。

つまり、denyルールは「input.amiがapproved_amisに含まれていない場合、Regulaのチェックは失敗し、エラーメッセージを返す」と指定しています。

エラーメッセージは次の行で定義します。

msg = sprintf("%s is not an approved AMI ID", [input.ami])

ここではRegoの組み込み関数sprintfを使って、評価中のリソースのamiを出力します。

これでカスタムルールは完成です。全体はこちらで確認できます。それではRegulaを実際に使ってみましょう。

Regulaでカスタムルールを実行する

それでは、シンプルなTerraformファイルでルールをテストしてみましょう。GitHub gistにあるTerraform HCLでは、EC2インスタンスを2つ定義しています。1つは承認済みAMI IDami-09e67e426f25ce0d7を使う「良い」インスタンス、もう1つは、まったく怪しくないAMI IDami-totallylegitamiidを使う「悪い」インスタンスです。

Regulaを実行する

ターミナルで、コードファイルがあるディレクトリにcdで移動し、次のコマンドを実行します。

regula run ami.tf --include approved_ami.rego --user-only

このコマンドはTerraformファイルに対してカスタムルールを実行します。--user-onlyフラグは、カスタムルールだけを適用するよう指定します。この記事では、Regulaの組み込みルールライブラリを対象から除外しています。(ただし、regula runを実行するとデフォルトで適用される組み込みルールの使用をおすすめします。)

次のような出力が表示されます。

AWS EC2インスタンスのAMIポリシー違反を示すターミナル出力:AMI IDが承認されていません。

ご覧のとおり、Terraformファイルはルールに違反し、ami-totallylegitamiid is not an approved AMI IDというメッセージが表示されました。これは、カスタムルールが機能したことを意味します。Regulaは、aws_instance.badインスタンス(13行目、1列目)に承認済みAMI IDが設定されていないことを示しました。

詳細なレポートを見る

詳細を確認するため、JSON形式のレポート全体を見てみましょう。

regula run ami.tf --include approved_ami.rego --user-only --format json

ここでは、すべてのルール結果を含む出力全体を確認できます。下の例では、aws_instance.badの結果が再びFAILである一方、aws_instance.goodのルール結果はPASSになっています。

{
  "rule_results": [
    {
      "controls": [
        "CORPORATE-POLICY_1.2"
      ],
      "filepath": "ami.tf",
      "input_type": "tf",
      "provider": "aws",
      "resource_id": "aws_instance.bad",
      "resource_type": "aws_instance",
      "rule_description": "Per company policy, EC2 instances may only use AMI IDs from a pre-approved list",
      "rule_id": "CUSTOM_0002",
      "rule_message": "ami-totallylegitamiid is not an approved AMI ID",
      "rule_name": "approved_ami",
      "rule_result": "FAIL",
      "rule_severity": "High",
      "rule_summary": "AWS EC2 instances must use approved AMIs",
      "source_location": [
        {
          "path": "ami.tf",
          "line": 13,
          "column": 1
        }
      ]
    },
    {
      "controls": [
        "CORPORATE-POLICY_1.2"
      ],
      "filepath": "ami.tf",
      "input_type": "tf",
      "provider": "aws",
      "resource_id": "aws_instance.good",
      "resource_type": "aws_instance",
      "rule_description": "Per company policy, EC2 instances may only use AMI IDs from a pre-approved list",
      "rule_id": "CUSTOM_0002",
      "rule_message": "",
      "rule_name": "approved_ami",
      "rule_result": "PASS",
      "rule_severity": "High",
      "rule_summary": "AWS EC2 instances must use approved AMIs",
      "source_location": [
        {
          "path": "ami.tf",
          "line": 8,
          "column": 1
        }
      ]
    }
  ],
  "summary": {
    "filepaths": [
      "ami.tf"
    ],
    "rule_results": {
      "FAIL": 1,
      "PASS": 1,
      "WAIVED": 0
    },
    "severities": {
      "Critical": 0,
      "High": 1,
      "Informational": 0,
      "Low": 0,
      "Medium": 0,
      "Unknown": 0
    }
  }
}

先ほどルールで定義した残りのメタデータも確認できます。

Terraformを修正する

Terraformを準拠させるには、ami.tfを編集し、ami-totallylegitamiidをami-09e67e426f25ce0d7に置き換えてから、Regulaをもう一度実行します。今度はデフォルトのテキスト形式を使います。

regula run ami.tf --include approved_ami.rego --user-only

次のような出力が表示されます。

No problems found.

成功です。Regulaで確認したとおり、承認済みAMIのみを使用することでTerraform IaCを保護できました。

さらに詳しく

この記事では、Regoでカスタムルールを作成し、Regulaを使ってTerraform HCLファイルに対してチェックを実行し、Terraformを準拠させました。

Regulaについて詳しく知りたい方は、Regulaのドキュメントサイトをご覧ください。次のリソースも参考になります。

開発者のために設計されたIaCセキュリティ

Snykは、統合されたポリシー・アズ・コードエンジンにより、SDLCからクラウドでの実行時までInfrastructure as Codeを保護します。すべてのチームが安全に開発、デプロイ、運用できるよう支援します。

続きを読む

feature customer snowflake
Article

開発初期からセキュリティを確保:Snowflake Cortex Code向けSnyk Studioインテグレーションを発表

Snyk StudioがSnowflake Cortex Codeと連携し、開発中にAI生成コード、依存関係、コンテナの脆弱性をスキャンします。

Article

Miasmaサプライチェーン攻撃:@redhat-cloud-servicesのnpmパッケージで悪意あるコードを確認

Miasmaと呼ばれるサプライチェーンワームが、@redhat-cloud-servicesの数十件のnpmリリースで見つかりました。悪意あるpreinstallフックは認証情報を窃取し、クラウドIDを調査して、他のパッケージを再公開する可能性があります。

Blog

QinglongタスクスケジューラーのRCE脆弱性が悪用され、暗号資産マイニングに利用

Qinglongタスクスケジューリングパネルに存在する2つの認証バイパス脆弱性(CVE-2026-3965、CVE-2026-4047)が実際に悪用され、暗号資産マイニングマルウェアが展開されました。何が起きたのか、攻撃の手口、そしてセルフホスト型アプリケーションの運用者がこのインシデントから学ぶべきことを解説します。