# IAM Policy to restrict direct access to break-glass workflow resources.
resource "aws_iam_policy" "break_glass_restrict_direct_access_policy" {
  name   = local.break_glass_restrict_direct_access_policy_name
  policy = data.aws_iam_policy_document.break_glass_restrict_direct_access_policy_document.json
  tags   = local.tags
}

data "aws_iam_policy_document" "break_glass_restrict_direct_access_policy_document" {
  statement {
    effect = "Deny"
    actions = [
      "lambda:InvokeAsync",
      "lambda:InvokeFunction",
    ]
    resources = [
      module.elevate_permissions_lambda.lambda_arn,
      "${module.elevate_permissions_lambda.lambda_arn}:*"
    ]
  }
}

# IAM Role that will be assumed to get elevated permissions.
resource "aws_iam_role" "break_glass_role" {
  name                 = local.break_glass_role_name
  assume_role_policy   = data.aws_iam_policy_document.break_glass_assume_role_policy.json
  max_session_duration = var.role_session_duration
  tags                 = local.tags
}

data "aws_iam_policy_document" "break_glass_assume_role_policy" {
  statement {
    actions = ["sts:AssumeRole"]
    principals {
      type        = "AWS"
      identifiers = [data.aws_caller_identity.current.account_id]
    }
  }
}

# Attach existing IAM Policies to the role.
data "aws_iam_policy" "break_glass_role_existing_policies" {
  for_each = toset(var.role_policies)
  name     = each.value
}

resource "aws_iam_role_policy_attachment" "break_glass_role_existing_policy_attachments" {
  for_each = toset(var.role_policies)

  role       = aws_iam_role.break_glass_role.name
  policy_arn = data.aws_iam_policy.break_glass_role_existing_policies[each.value].arn
}

# Attach elevated permissions IAM Policy to the role.
data "aws_iam_policy" "break_glass_elevate_permissions_policy" {
  name = local.break_glass_elevate_permissions_policy_name
}

resource "aws_iam_role_policy_attachment" "break_glass_role_elevate_permissions_policy_attachment" {
  role       = aws_iam_role.break_glass_role.name
  policy_arn = data.aws_iam_policy.break_glass_elevate_permissions_policy.arn
}

# Allow lambda function assume the validation role in this account
data "aws_iam_policy_document" "elevate_permissions_validate_lambda_role" {
  version = "2012-10-17"
  statement {
    effect = "Allow"
    principals {
      identifiers = [
        module.elevate_permissions_lambda.lambda_role_arn
      ]
      type = "AWS"
    }
    actions = ["sts:AssumeRole"]
  }
}

resource "aws_iam_role" "elevate_permissions_validate_lambda_role" {
  name               = local.break_glass_validate_role_name
  assume_role_policy = data.aws_iam_policy_document.elevate_permissions_validate_lambda_role.json
}

data "aws_iam_policy_document" "elevate_permissions_validate_lambda_policy_document" {
  statement {
    effect = "Allow"
    actions = [
      "iam:GetRole",
    ]
    resources = [
      aws_iam_role.break_glass_role.arn
    ]
  }
}

resource "aws_iam_policy" "elevate_permissions_validate_lambda_policy" {
  name   = "${var.environment}-break-glass-validate"
  policy = data.aws_iam_policy_document.elevate_permissions_validate_lambda_policy_document.json
  tags   = local.tags
}

resource "aws_iam_role_policy_attachment" "elevate_permissions_validate_lambda_policy_attachment" {
  policy_arn = aws_iam_policy.elevate_permissions_validate_lambda_policy.arn
  role       = aws_iam_role.elevate_permissions_validate_lambda_role.name
}
