data "aws_caller_identity" "this" {}

data "aws_iam_policy_document" "logging_policy" {
  # checkov:skip=CKV_AWS_111:Ensure IAM policies does not allow write access without constraints
  version = "2012-10-17"
  statement {
    effect = "Allow"
    actions = [
      "logs:CreateLogStream",
      "logs:CreateLogGroup",
      "logs:DescribeLogGroups",
      "logs:DescribeLogStreams",
      "logs:PutLogEvents",
    ]
    resources = ["*"]
  }
}

resource "aws_iam_policy" "logging_policy" {
  name        = "CloudWatch-${local.name_prefix}-RW"
  path        = "/"
  description = "Allows creating log groups, log streams and putting log events into cloudwatch logs"
  policy      = data.aws_iam_policy_document.logging_policy.json
}

// ExecuteStateMachineRole
data "aws_iam_policy_document" "assume_execute_state_machine_role_policy" {
  version = "2012-10-17"

  statement {
    sid    = "AllowCWEServiceToAssumeRole"
    effect = "Allow"

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

    actions = ["sts:AssumeRole"]
  }
}

resource "aws_iam_role" "execute_state_machine_role" {
  name               = "${local.name_prefix}-execute-state-machine-role"
  assume_role_policy = data.aws_iam_policy_document.assume_execute_state_machine_role_policy.json
}

data "aws_iam_policy_document" "execute_state_machine_policy" {
  version = "2012-10-17"
  statement {
    effect    = "Allow"
    actions   = ["states:StartExecution"]
    resources = ["arn:aws:states:${var.aws_region}:${local.account_id}:stateMachine:${local.name_prefix}-ExposedKeyStepFunction"]
  }
}

resource "aws_iam_policy" "execute_state_machine_policy" {
  name   = "StepFunctions-${local.name_prefix}-StartExecution"
  policy = data.aws_iam_policy_document.execute_state_machine_policy.json
}

resource "aws_iam_role_policy_attachment" "execute_state_machine_policy" {
  policy_arn = aws_iam_policy.execute_state_machine_policy.arn
  role       = aws_iam_role.execute_state_machine_role.name
}

// StepFunctionExecutionRole
data "aws_iam_policy_document" "assume_step_function_execution_role_policy" {
  version = "2012-10-17"

  statement {
    effect = "Allow"

    principals {
      type        = "Service"
      identifiers = ["states.${var.aws_region}.amazonaws.com"]
    }

    actions = ["sts:AssumeRole"]
  }
}

resource "aws_iam_role" "step_function_execution_role" {
  name               = "${local.name_prefix}-step-function-execution-role"
  assume_role_policy = data.aws_iam_policy_document.assume_step_function_execution_role_policy.json
}

data "aws_iam_policy_document" "states_execution_policy" {
  version = "2012-10-17"
  statement {
    effect  = "Allow"
    actions = ["lambda:InvokeFunction"]
    resources = formatlist(
      "arn:aws:lambda:${var.aws_region}:${local.account_id}:function:%s",
      [
        local.delete_access_key_pair_resource_name,
        local.lookup_cloudtrail_events_resource_name,
        local.notify_security_resource_name,
      ]
    )
  }
}

resource "aws_iam_policy" "states_execution_policy" {
  name   = "Lambda-${local.name_prefix}-InvokePolicy"
  policy = data.aws_iam_policy_document.states_execution_policy.json
}

resource "aws_iam_role_policy_attachment" "states_execution_policy" {
  policy_arn = aws_iam_policy.states_execution_policy.arn
  role       = aws_iam_role.step_function_execution_role.name
}

// LambdaDeleteAccessKeyPairRole
data "aws_iam_policy_document" "delete_access_key_pair_lambda_role" {
  statement {
    effect = "Allow"

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

    actions = ["sts:AssumeRole"]
  }
}

resource "aws_iam_role" "delete_access_key_pair_lambda_role" {
  name               = "${local.name_prefix}-delete-access-key-pair-role"
  assume_role_policy = data.aws_iam_policy_document.delete_access_key_pair_lambda_role.json
}

data "aws_iam_policy_document" "delete_access_key_pair_lambda_policy" {
  # checkov:skip=CKV_AWS_111:Ensure IAM policies does not allow write access without constraints
  # we cannot limit the scope to the particular users because theoretically any key can get exposed

  # checkov:skip=CKV_AWS_107:Ensure IAM policies does not allow credentials exposure
  # checkov:skip=CKV_AWS_109:Ensure IAM policies does not allow permissions management / resource exposure without constraints
  version = "2012-10-17"
  statement {
    effect = "Allow"
    actions = [
      "iam:UpdateAccessKey",
      "iam:GetAccessKeyLastUsed",
    ]
    resources = ["*"]
  }
}

resource "aws_iam_policy" "delete_access_key_pair_lambda_policy" {
  name   = "IAM-${local.name_prefix}-DeleteAccessKey"
  policy = data.aws_iam_policy_document.delete_access_key_pair_lambda_policy.json
}

resource "aws_iam_role_policy_attachment" "delete_access_key_pair_lambda_policy" {
  policy_arn = aws_iam_policy.delete_access_key_pair_lambda_policy.arn
  role       = aws_iam_role.delete_access_key_pair_lambda_role.name
}

resource "aws_iam_role_policy_attachment" "delete_access_key_pair_lambda_logging_policy" {
  policy_arn = aws_iam_policy.logging_policy.arn
  role       = aws_iam_role.delete_access_key_pair_lambda_role.name
}

// LambdaLookupCloudTrailEventsRole
data "aws_iam_policy_document" "lookup_cloudtrail_events_lambda_role" {
  statement {
    effect = "Allow"

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

    actions = ["sts:AssumeRole"]
  }
}

resource "aws_iam_role" "lookup_cloudtrail_events_lambda_role" {
  name               = "${local.name_prefix}-lookup-cloudtrail-events-role"
  assume_role_policy = data.aws_iam_policy_document.lookup_cloudtrail_events_lambda_role.json
}

data "aws_iam_policy_document" "lookup_cloudtrail_events_lambda_policy" {
  version = "2012-10-17"
  statement {
    effect = "Allow"
    actions = [
      "cloudtrail:LookupEvents",
    ]
    resources = ["*"]
  }
}

resource "aws_iam_policy" "lookup_cloudtrail_events_lambda_policy" {
  name   = "CloudTrail-${local.name_prefix}-LookupEvents"
  policy = data.aws_iam_policy_document.lookup_cloudtrail_events_lambda_policy.json
}

resource "aws_iam_role_policy_attachment" "lookup_cloudtrail_events_lambda_policy" {
  policy_arn = aws_iam_policy.lookup_cloudtrail_events_lambda_policy.arn
  role       = aws_iam_role.lookup_cloudtrail_events_lambda_role.name
}

resource "aws_iam_role_policy_attachment" "lookup_cloudtrail_events_lambda_logging_policy" {
  policy_arn = aws_iam_policy.logging_policy.arn
  role       = aws_iam_role.lookup_cloudtrail_events_lambda_role.name
}

// LambdaLookupCloudTrailEventsRole
data "aws_iam_policy_document" "notify_security_lambda_role" {
  statement {
    effect = "Allow"

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

    actions = ["sts:AssumeRole"]
  }
}

resource "aws_iam_role" "notify_security_lambda_role" {
  name               = "${local.name_prefix}-notify-security-role"
  assume_role_policy = data.aws_iam_policy_document.notify_security_lambda_role.json
}

data "aws_iam_policy_document" "notify_security_lambda_policy" {
  version = "2012-10-17"
  statement {
    effect = "Allow"
    actions = [
      "sns:Publish",
    ]
    resources = [aws_sns_topic.notification_topic.arn]
  }
}

resource "aws_iam_policy" "notify_security_lambda_policy" {
  name   = "SNS-${local.name_prefix}-Publish"
  policy = data.aws_iam_policy_document.notify_security_lambda_policy.json
}

resource "aws_iam_role_policy_attachment" "notify_security_lambda_policy" {
  policy_arn = aws_iam_policy.notify_security_lambda_policy.arn
  role       = aws_iam_role.notify_security_lambda_role.name
}

resource "aws_iam_role_policy_attachment" "notify_security_lambda_logging_policy" {
  policy_arn = aws_iam_policy.logging_policy.arn
  role       = aws_iam_role.notify_security_lambda_role.name
}
