# Optional secret-specific KMS encryption key
resource "aws_kms_key" "kms_key" {
  count       = var.custom_kms_key_enabled ? 1 : 0
  description = format("alias/%s-%s-%s", var.environment, var.service_name, var.secret_name)

  tags = local.combined_resource_tags
}

resource "aws_kms_alias" "kms_alias" {
  count         = var.custom_kms_key_enabled ? 1 : 0
  name          = format("alias/%s-%s-%s", var.environment, var.service_name, var.secret_name)
  target_key_id = aws_kms_key.kms_key.0.key_id
}

resource "aws_secretsmanager_secret" "secret" {
  name                    = format("%s/%s/%s", var.environment, var.service_name, var.secret_name)
  description             = var.custom_secret_description != "" ? var.custom_secret_description : format("%s/%s/%s", var.environment, var.service_name, var.secret_name)
  recovery_window_in_days = var.secret_recovery_window_in_days
  kms_key_id              = var.custom_kms_key_enabled ? aws_kms_key.kms_key.0.id : null

  dynamic "replica" {
    for_each = var.secret_replication_regions
    content {
      kms_key_id = var.custom_kms_key_enabled ? aws_kms_key.kms_key.0.id : null
      region     = replica.value
    }
  }

  tags = local.combined_resource_tags
}

resource "aws_secretsmanager_secret_version" "secret_string" {
  secret_id      = aws_secretsmanager_secret.secret.id
  secret_string  = length(var.secret_map) != 0 ? jsonencode(var.secret_map) : var.secret_string
  version_stages = var.version_stages

  lifecycle {
    ignore_changes = [
      id,
      secret_id,
      secret_string,
      version_stages,
    ]
  }
}

data "aws_arn" "rotation_lambda_function" {
  count = var.secret_rotation_enabled ? 1 : 0
  arn   = var.secret_rotation_lambda_arn
}

data "aws_lambda_function" "rotation_lambda_function" {
  count         = var.secret_rotation_enabled ? 1 : 0
  function_name = data.aws_arn.rotation_lambda_function[0].resource
}

resource "aws_lambda_permission" "allow_secrets_manager_invocation" {
  count         = var.secret_rotation_enabled && var.secret_rotation_lambda_permission ? 1 : 0
  statement_id  = "SecretsManager-${format("%s-%s-%s", var.environment, var.service_name, var.secret_name)}"
  action        = "lambda:InvokeFunction"
  function_name = data.aws_lambda_function.rotation_lambda_function[0].function_name
  principal     = "secretsmanager.amazonaws.com"
  source_arn    = aws_secretsmanager_secret.secret.arn
}

resource "aws_secretsmanager_secret_rotation" "secret_rotation" {
  # checkov:skip=CKV_AWS_304:Ensure Secrets Manager secrets should be rotated within 90 days
  count      = var.secret_rotation_enabled ? 1 : 0
  depends_on = [aws_secretsmanager_secret_version.secret_string]

  secret_id           = aws_secretsmanager_secret.secret.id
  rotation_lambda_arn = data.aws_lambda_function.rotation_lambda_function[0].arn

  rotate_immediately = var.secret_rotation_rotate_immediately

  rotation_rules {
    automatically_after_days = var.secret_rotation_interval_in_days != null ? var.secret_rotation_interval_in_days : null
    schedule_expression      = var.secret_rotation_schedule_expression != null ? var.secret_rotation_schedule_expression : null
    duration                 = var.secret_rotation_window_duration != null ? var.secret_rotation_window_duration : null
  }

  lifecycle {
    # Only one of the rotation scheduling variables may be set
    precondition {
      condition     = (var.secret_rotation_interval_in_days == null && var.secret_rotation_schedule_expression == null) ? false : true
      error_message = "Please set one of var.secret_rotation_interval_in_days or var.secret_rotation_schedule_expression"
    }
    postcondition {
      condition     = (var.secret_rotation_interval_in_days != null && var.secret_rotation_schedule_expression != null) ? false : true
      error_message = "Please set only one of var.secret_rotation_interval_in_days or var.secret_rotation_schedule_expression"
    }
  }
}
