Task: Generate a Kinesis Firehose Delivery Stream with an OpenSearch destination

Specification:
Has one "aws_iam_role" resource, one "aws_s3_bucket" resource, one "aws_opensearch_domain" resource, and one "aws_kinesis_firehose_delivery_stream" resource with an "opensearch_configuration" block

Terraform configuration (main.tf):
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">= 5.75"
    }
  }

  required_version = ">= 1.9.0"
}

provider "aws" {
  region  = "us-east-1"
}


resource "aws_s3_bucket" "januaryseventh" {
  bucket = "januaryseventh"
}

resource "aws_opensearch_domain" "test_cluster" {
  domain_name = "es-test-3"

  cluster_config {
    instance_count         = 2
    zone_awareness_enabled = true
    instance_type          = "m4.large.search"
  }

  ebs_options {
    ebs_enabled = true
    volume_size = 10
  }
}

data "aws_iam_policy_document" "firehose_assume_role" {
  statement {
    effect = "Allow"

    principals {
      type        = "Service"
      identifiers = ["firehose.amazonaws.com"]
    }

    actions = ["sts:AssumeRole"]
  }
}

resource "aws_iam_role" "firehose_role" {
  name               = "firehose_test_role"
  assume_role_policy = data.aws_iam_policy_document.firehose_assume_role.json
}

data "aws_iam_policy_document" "firehose-opensearch" {
  statement {
    effect  = "Allow"
    actions = ["es:*"]

    resources = [
      aws_opensearch_domain.test_cluster.arn,
      "${aws_opensearch_domain.test_cluster.arn}/*",
    ]
  }
}

resource "aws_iam_role_policy" "firehose-opensearch" {
  name   = "opensearch"
  role   = aws_iam_role.firehose_role.id
  policy = data.aws_iam_policy_document.firehose-opensearch.json
}

data "aws_iam_policy_document" "main" {
  statement {
    effect = "Allow"

    principals {
      type        = "*"
      identifiers = ["*"]
    }

    condition {
      test     = "IpAddress"
      variable = "aws:SourceIp"
      values   = ["127.0.0.1/32"]
    }

    actions   = ["es:*"]
    resources = ["${aws_opensearch_domain.test_cluster.arn}/*"]
  }
}

# applied at service level, necessary for opensearch access
resource "aws_opensearch_domain_policy" "main" {
  domain_name     = aws_opensearch_domain.test_cluster.domain_name
  access_policies = data.aws_iam_policy_document.main.json
}

resource "aws_kinesis_firehose_delivery_stream" "test" {
  depends_on = [aws_iam_role_policy.firehose-opensearch]

  name        = "terraform-kinesis-firehose-os"
  destination = "opensearch"

  opensearch_configuration {
    domain_arn = aws_opensearch_domain.test_cluster.arn
    role_arn   = aws_iam_role.firehose_role.arn
    index_name = "test"

    s3_configuration {
      role_arn   = aws_iam_role.firehose_role.arn
      bucket_arn = aws_s3_bucket.januaryseventh.arn
      buffering_size     = 10
      buffering_interval = 400
      compression_format = "GZIP"
    }
  }
}

Validation policy (checks.rego):
package terraform.validation

import future.keywords.in

default has_valid_resources = false

has_valid_iam_role(resources) { 
        some resource in resources 
    resource.type == "aws_iam_role" 
    contains(resource.change.after.assume_role_policy,"firehose.amazonaws.com") 
}

has_valid_bucket {
    some i
    resource := input.planned_values.root_module.resources[i]
    resource.type == "aws_s3_bucket"
}

has_valid_opensearch_cluster {
    some i
    resource := input.planned_values.root_module.resources[i]
    resource.type == "aws_opensearch_domain"
    resource.values.domain_name
}

has_valid_firehose_delivery_stream {
        some i
        resource := input.planned_values.root_module.resources[i]
    resource.type == "aws_kinesis_firehose_delivery_stream"
    resource.values.name
    resource.values.destination == "opensearch"
    resource.values.opensearch_configuration[_].s3_configuration
        role := input.configuration.root_module.resources[i]
    role.expressions.opensearch_configuration[_].role_arn
    role.expressions.opensearch_configuration[_].domain_arn
}

has_valid_resources {
        has_valid_iam_role(input.resource_changes)
        has_valid_bucket
    has_valid_opensearch_cluster
    has_valid_firehose_delivery_stream
}