locals {
  account_alias = data.aws_iam_account_alias.current.account_alias
  web_acl_name  = "${local.account_alias}_web_acl"
}

data "aws_iam_account_alias" "current" {}

data "aws_wafv2_web_acl" "main" {
  name  = local.web_acl_name
  scope = "REGIONAL"
}

module "sftp_transfer_server" {
  source = "../sftp"

  name_prefix            = var.name_prefix
  endpoint_type          = var.endpoint_type
  identity_provider_type = "API_GATEWAY"
  invocation_role        = aws_iam_role.TransferIdentityProviderRole.arn
  url                    = "https://${aws_api_gateway_rest_api.CustomIdentityProviderApi.id}.execute-api.${var.region}.amazonaws.com/${aws_api_gateway_stage.ApiStage.stage_name}"
  project                = var.project
  aggregated_tag         = var.aggregated_tag
  address_allocation_ids = var.address_allocation_ids
  subnet_ids             = var.subnet_ids
  vpc_id                 = var.vpc_id
  common_tags            = var.common_tags
  security_policy_name   = var.security_policy_name
}

resource "aws_api_gateway_rest_api" "CustomIdentityProviderApi" {
  name        = "${var.name_prefix}-sftp-custom-idp"
  description = "API used for GetUserConfig requests"

  endpoint_configuration {
    types = ["REGIONAL"]
  }

  tags = merge(
    var.common_tags,
    {
      service                  = "API Gateway",
      plat_env_project_service = "${var.aggregated_tag}_${var.project}_AGW"
    }
  )
}

module "LambdaExecutionRole" {
  source = "../../iam/roles/lambda_role"

  name          = "lambda-role"
  name_prefix   = var.name_prefix
  policies_list = var.lambda_policies
}

resource "aws_iam_role" "CloudWatchLoggingRole" {
  name = "${var.name_prefix}-api-gw-logging-role"

  assume_role_policy = <<EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
        "Effect": "Allow",
        "Principal": {
            "Service": "apigateway.amazonaws.com"
        },
        "Action": "sts:AssumeRole"
        }
    ]
}
EOF
}

data "aws_iam_policy_document" "CloudWatchLoggingPolicyDocument" {
  statement {
    sid    = "AllowApiGatewayLogs"
    effect = "Allow"
    actions = [
      "logs:CreateLogGroup",
      "logs:CreateLogStream",
      "logs:DescribeLogGroups",
      "logs:DescribeLogStreams",
      "logs:PutLogEvents",
      "logs:GetLogEvents",
      "logs:FilterLogEvents"
    ]
    resources = ["*"]
  }
}

resource "aws_iam_role_policy" "CloudWatchLoggingPolicy" {
  name   = "${var.name_prefix}-cw-logging-policy"
  role   = aws_iam_role.CloudWatchLoggingRole.id
  policy = data.aws_iam_policy_document.CloudWatchLoggingPolicyDocument.json
}

resource "aws_api_gateway_account" "ApiLoggingAccount" {
  cloudwatch_role_arn = aws_iam_role.CloudWatchLoggingRole.arn
}

resource "aws_api_gateway_model" "GetUserConfigResponseModel" {
  rest_api_id  = aws_api_gateway_rest_api.CustomIdentityProviderApi.id
  name         = "UserConfigResponseModel"
  description  = "API response for GetUserConfig"
  content_type = "application/json"

  schema = <<EOF
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "title": "UserUserConfig",
  "type": "object",
  "properties": {
      "HomeDirectory": {
          "type": "string"
      },
      "Role": {
          "type": "string"
      },
      "Policy": {
          "type": "string"
      },
      "PublicKeys": {
          "type": "array",
          "items": {
              "type": "string"
          }
      }
  }
}
EOF
}

resource "aws_api_gateway_resource" "ServersResource" {
  parent_id   = aws_api_gateway_rest_api.CustomIdentityProviderApi.root_resource_id
  path_part   = "servers"
  rest_api_id = aws_api_gateway_rest_api.CustomIdentityProviderApi.id
}

resource "aws_api_gateway_resource" "ServerIdResource" {
  parent_id   = aws_api_gateway_resource.ServersResource.id
  path_part   = "{serverId}"
  rest_api_id = aws_api_gateway_rest_api.CustomIdentityProviderApi.id
}

resource "aws_api_gateway_resource" "UsersResource" {
  parent_id   = aws_api_gateway_resource.ServerIdResource.id
  path_part   = "users"
  rest_api_id = aws_api_gateway_rest_api.CustomIdentityProviderApi.id
}

resource "aws_api_gateway_resource" "UserNameResource" {
  parent_id   = aws_api_gateway_resource.UsersResource.id
  path_part   = "{username}"
  rest_api_id = aws_api_gateway_rest_api.CustomIdentityProviderApi.id
}

resource "aws_api_gateway_resource" "GetUserConfigResource" {
  parent_id   = aws_api_gateway_resource.UserNameResource.id
  path_part   = "config"
  rest_api_id = aws_api_gateway_rest_api.CustomIdentityProviderApi.id
}

resource "aws_api_gateway_method" "GetUserConfigRequest" {
  authorization = "AWS_IAM"
  http_method   = "GET"
  resource_id   = aws_api_gateway_resource.GetUserConfigResource.id
  rest_api_id   = aws_api_gateway_rest_api.CustomIdentityProviderApi.id

  request_parameters = {
    "method.request.header.Password"      = false
    "method.request.querystring.protocol" = false
    "method.request.querystring.sourceIp" = false
  }
}

resource "aws_api_gateway_method_response" "GetUserConfigRequest" {
  http_method = aws_api_gateway_method.GetUserConfigRequest.http_method
  resource_id = aws_api_gateway_resource.GetUserConfigResource.id
  rest_api_id = aws_api_gateway_rest_api.CustomIdentityProviderApi.id
  status_code = "200"

  response_models = {
    "application/json" = "UserConfigResponseModel"
  }

  depends_on = [aws_api_gateway_model.GetUserConfigResponseModel]
}

resource "aws_api_gateway_integration" "GetUserConfigRequest" {
  http_method             = aws_api_gateway_method.GetUserConfigRequest.http_method
  integration_http_method = "POST"
  resource_id             = aws_api_gateway_resource.GetUserConfigResource.id
  rest_api_id             = aws_api_gateway_rest_api.CustomIdentityProviderApi.id
  type                    = "AWS"
  uri                     = module.GetUserConfigLambda.this.invoke_arn

  request_templates = {
    "application/json" = <<TEMPLATE
{
  "username": "$util.urlDecode($input.params('username'))",
  "password": "$util.escapeJavaScript($input.params('Password')).replaceAll("\\'","'")",
  "protocol": "$input.params('protocol')",
  "serverId": "$input.params('serverId')",
  "sourceIp": "$input.params('sourceIp')"
}
TEMPLATE
  }
}

resource "aws_api_gateway_integration_response" "GetUserConfigRequest" {
  http_method = aws_api_gateway_method.GetUserConfigRequest.http_method
  resource_id = aws_api_gateway_resource.GetUserConfigResource.id
  rest_api_id = aws_api_gateway_rest_api.CustomIdentityProviderApi.id
  status_code = aws_api_gateway_method_response.GetUserConfigRequest.status_code

  depends_on = [aws_api_gateway_integration.GetUserConfigRequest]
}

resource "aws_api_gateway_stage" "ApiStage" {
  deployment_id        = aws_api_gateway_deployment.ApiDeployment202008.id
  rest_api_id          = aws_api_gateway_rest_api.CustomIdentityProviderApi.id
  stage_name           = "prod"
  xray_tracing_enabled = false
}

resource "aws_api_gateway_method_settings" "ApiStage" {
  rest_api_id = aws_api_gateway_rest_api.CustomIdentityProviderApi.id
  stage_name  = aws_api_gateway_stage.ApiStage.stage_name
  method_path = "*/*"

  settings {
    metrics_enabled    = true
    data_trace_enabled = false
    logging_level      = "INFO"
  }
}

resource "aws_api_gateway_deployment" "ApiDeployment202008" {
  rest_api_id = aws_api_gateway_rest_api.CustomIdentityProviderApi.id

  depends_on = [
    aws_api_gateway_method.GetUserConfigRequest,
    aws_api_gateway_integration.GetUserConfigRequest,
  ]
}

resource "aws_iam_role" "TransferIdentityProviderRole" {
  name        = "${var.name_prefix}_idp_role"
  description = ""

  assume_role_policy = <<EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
        "Effect": "Allow",
        "Principal": {
            "Service": "transfer.amazonaws.com"
        },
        "Action": "sts:AssumeRole"
        }
    ]
}
EOF
}

data "aws_iam_policy_document" "TransferIdentityProviderRolePolicyDocument" {
  statement {
    sid       = "TransferCanInvokeThisApi"
    effect    = "Allow"
    actions   = ["execute-api:Invoke"]
    resources = ["arn:aws:execute-api:${var.region}:${var.account_id}:${aws_api_gateway_rest_api.CustomIdentityProviderApi.id}/prod/GET/*"]
  }

  statement {
    sid       = "TransferCanReadThisApi"
    effect    = "Allow"
    actions   = ["apigateway:GET"]
    resources = ["*"]
  }
}

resource "aws_iam_role_policy" "TransferIdentityProviderRolePolicy" {
  policy = data.aws_iam_policy_document.TransferIdentityProviderRolePolicyDocument.json
  role   = aws_iam_role.TransferIdentityProviderRole.id
}

module "GetUserConfigLambda" {
  source = "../aws_transfer_idp_lambda"

  role         = module.LambdaExecutionRole.role.arn
  secrets_path = var.secrets_path
  source_arn   = "${aws_api_gateway_rest_api.CustomIdentityProviderApi.execution_arn}/*"

  tags = merge(
    var.common_tags,
    {
      service                  = "Lambda",
      plat_env_project_service = "${var.aggregated_tag}_${var.project}_LMB"
    }
  )
}

resource "aws_wafv2_web_acl_association" "main" {
  count = var.enable_ip_blocking ? 1 : 0

  resource_arn = aws_api_gateway_stage.ApiStage.arn
  web_acl_arn  = data.aws_wafv2_web_acl.main.arn
}
