module "s3_artifact_bucket" {
  source = "git@github.com:theorchard/terraform-s3.git//modules/s3_bucket?ref=3.14.1"

  env                 = var.environment
  application_family  = var.application_family
  bucket_name         = "${var.service_name}-artifacts"
  s3_read_only_policy = true

  apply_server_side_encryption_by_default = {
    sse_algorithm = "AES256"
  }
}

data "aws_iam_policy_document" "jenkins_assume_role_policy" {
  statement {
    actions = ["sts:AssumeRole"]

    principals {
      type = "AWS"

      identifiers = [
        "arn:aws:iam::437795906767:role/prod-jenkins-aws-pipeline-agent",
      ]
    }
  }
}

resource "aws_iam_role" "s3_artifact_read_role" {
  name               = "${var.environment}-s3-${var.service_name}-artifacts-read"
  assume_role_policy = data.aws_iam_policy_document.jenkins_assume_role_policy.json
}

resource "aws_iam_role_policy_attachment" "s3_artifact_read_policy_attachments" {
  role       = aws_iam_role.s3_artifact_read_role.id
  policy_arn = module.s3_artifact_bucket.s3_read_only_policy_arn_output
}

module "s3_artifacts_write_policy" {
  source = "git@github.com:theorchard/terraform-iam-policy-templates.git//documents/s3/buckets_with_prefixes?ref=0.4.0"

  buckets = [{
    bucket = module.s3_artifact_bucket.s3_bucket_name_output
  }]

  action_types = ["read", "write"]
}

resource "aws_iam_policy" "s3_artifacts_read_write_policy" {
  name   = "S3-${module.s3_artifact_bucket.s3_bucket_name_output}-RW"
  policy = module.s3_artifacts_write_policy.policy.json
}

# The lambda will need this policy in order to assume the backup role in one or many accounts
data "aws_iam_policy_document" "assume_cross_account_backup_role_policy_document" {
  statement {
    actions = [
      "sts:AssumeRole",
    ]

    resources = [
      for backup_target_account in module.aws_accounts.all_accounts :
      "arn:aws:iam::${backup_target_account}:role/${var.cross_account_backup_role_name}"
    ]
  }
}

resource "aws_iam_policy" "assume_cross_account_backup_role_policy" {
  name        = "STS-${var.environment}-${var.service_name}-assume-cross-account-backup-role-policy"
  description = "STS-${var.environment}-${var.service_name}-assume-cross-account-backup-role-policy"
  policy      = data.aws_iam_policy_document.assume_cross_account_backup_role_policy_document.json
}

module "lambda_extract_native_configuration" {
  source = "git@github.com:theorchard/terraform-lambda.git//?ref=4.3.0"

  environment                                    = var.environment
  lambda_name                                    = "lambda-${var.service_name}-extract-native-configuration"
  application_family                             = var.application_family
  lambda_description                             = "Extracts native configuration from RDS instances"
  use_container_image                            = true
  datadog_advanced_enabled                       = true
  vpc_id                                         = module.vpc_info.vpc_id
  vpc_subnet_ids                                 = data.aws_subnets.rds_backup_subnets.ids
  lambda_function_timeout                        = 900
  lambda_function_reserved_concurrent_executions = 100
  iam_managed_policy_attachments = [
    aws_iam_policy.s3_artifacts_read_write_policy.arn,
    aws_iam_policy.assume_cross_account_backup_role_policy.arn,
  ]

  lambda_function_environment_variables = {
    CROSS_ACCOUNT_BACKUP_ROLE_NAME = var.cross_account_backup_role_name
    Environment                    = var.environment
    SENTRY_DSN                     = data.sentry_key.sentry_project_dsn_key.dsn["public"]
    STS_EXTERNAL_ID                = var.external_id
    S3_BUCKET_NAME                 = module.s3_artifact_bucket.s3_bucket_name_output
  }
}

data "aws_iam_policy_document" "step_function_invoke_lambda_role_assume_role_policy_document" {
  statement {
    actions = [
      "sts:AssumeRole",
    ]

    principals {
      type = "AWS"

      identifiers = [
        var.backup_account_role_arn
      ]
    }
  }
}

# The step function will need to invoke this lambda
resource "aws_iam_role" "step_function_invoke_lambda_role" {
  name               = "prod-${var.service_name}-step-function-invoke-lambda-role"
  assume_role_policy = data.aws_iam_policy_document.step_function_invoke_lambda_role_assume_role_policy_document.json
  tags = {
    environment        = var.environment
    application_family = var.application_family
    project            = var.service_name
    terraformed        = true
  }
}

data "aws_iam_policy_document" "lambda_extract_native_configuration_invoke_policy_document" {
  statement {
    actions = [
      "lambda:InvokeFunction",
    ]

    resources = [
      module.lambda_extract_native_configuration.lambda_arn,
    ]
  }
}

resource "aws_iam_policy" "lambda_extract_native_configuration_invoke_policy" {
  name        = "Lambda-${var.environment}-${var.service_name}-extract-native-configuration-invoke-policy"
  description = "Lambda-${var.environment}-${var.service_name}-extract-native-configuration-invoke-policy"
  policy      = data.aws_iam_policy_document.lambda_extract_native_configuration_invoke_policy_document.json
}

resource "aws_iam_role_policy_attachment" "lambda_extract_native_configuration_invoke_policy_attachment" {
  role       = aws_iam_role.step_function_invoke_lambda_role.name
  policy_arn = aws_iam_policy.lambda_extract_native_configuration_invoke_policy.arn
}
