module "default_tags" {
  source             = "git@github.com:theorchard/terraform-default-tags.git//?ref=2.0.0"
  environment        = var.environment
  application_family = var.application_family
  team_name          = var.team_name
  service_name       = var.service_name
}

provider "aws" {
  region = var.aws_region

  default_tags {
    tags = module.default_tags.tags
  }
}

# Terraform backends cannot contain interpolations
terraform {
  backend "s3" {
    bucket  = "prod-songwhip-terraform-state"
    key     = "prod/iam/generic_resources/terraform.tfstate"
    region  = "us-east-1"
    encrypt = "true"
  }
}

data "aws_caller_identity" "current" {}

# This service link role is used as a data source in terraform-fargate module.
resource "aws_iam_service_linked_role" "ecs_autoscaling_service_linked_role" {
  aws_service_name = "ecs.application-autoscaling.amazonaws.com"
}

# Fargate task execution policy document
data "aws_iam_policy_document" "fargate_task_execution_policy_document" {
  statement {
    actions = [
      "ecr:GetAuthorizationToken",
      "ecr:BatchCheckLayerAvailability",
      "ecr:GetDownloadUrlForLayer",
      "ecr:BatchGetImage",
    ]

    resources = [
      "*",
    ]
  }

  statement {
    actions = [
      "logs:*",
    ]

    resources = [
      "arn:aws:logs:*:${data.aws_caller_identity.current.account_id}:log-group:*",
    ]
  }
}

# Fargate task execution policy
resource "aws_iam_policy" "fargate_task_execution_policy" {
  name   = "Fargate-task-execution-policy"
  policy = data.aws_iam_policy_document.fargate_task_execution_policy_document.json

  tags = {
    terraformed = true
    application_family = "devops"
  }
}

# Fargate datadog secrets manager policy document
data "aws_iam_policy_document" "fargate_datadog_secret_policy_document" {
  statement {
    effect = "Allow"

    resources = [
      "arn:aws:secretsmanager:*:*:secret:${var.environment}/datadog/",
      "arn:aws:secretsmanager:*:*:secret:${var.environment}/datadog/*",
    ]

    actions = [
      "secretsmanager:ListSecretVersionIds",
      "secretsmanager:GetSecretValue",
      "secretsmanager:GetResourcePolicy",
      "secretsmanager:DescribeSecret",
    ]
  }

  statement {
    effect    = "Allow"
    resources = ["*"]
    actions   = ["secretsmanager:GetRandomPassword"]
  }
}

# Fargate datadog secrets manager policy
resource "aws_iam_policy" "fargate_datadog_secret_policy" {
  name   = "SecretsManager-${var.environment}-datadog-policy"
  policy = data.aws_iam_policy_document.fargate_datadog_secret_policy_document.json

  tags = {
    terraformed = true
    application_family = "devops"
  }
}

# Fargate machine to machine secrets manager policy document
data "aws_iam_policy_document" "machine_to_machine_secret_policy_document" {
  statement {
    effect = "Allow"

    resources = [
      "arn:aws:secretsmanager:${var.aws_region}:${data.aws_caller_identity.current.id}:secret:${var.environment}/ows-machine-to-machine/client_secret-*",
      "arn:aws:secretsmanager:${var.aws_region}:${data.aws_caller_identity.current.id}:secret:${var.environment}/lambda-jwt-refresh/jwt_token_expiration-*",
      "arn:aws:secretsmanager:${var.aws_region}:${data.aws_caller_identity.current.id}:secret:${var.environment}/lambda-jwt-refresh/jwt_token-*",
    ]

    actions = [
      "secretsmanager:ListSecretVersionIds",
      "secretsmanager:GetSecretValue",
      "secretsmanager:GetResourcePolicy",
      "secretsmanager:DescribeSecret",
    ]
  }

  statement {
    effect    = "Allow"
    resources = ["*"]
    actions   = ["secretsmanager:GetRandomPassword"]
  }

  statement {
    effect    = "Allow"
    resources = ["arn:aws:secretsmanager:${var.aws_region}:${data.aws_caller_identity.current.id}:secret:${var.environment}/lambda-jwt-refresh/jwt_enabled_services-*"]

    actions = [
      "secretsmanager:UpdateSecret",
      "secretsmanager:ListSecretVersionIds",
      "secretsmanager:GetSecretValue",
      "secretsmanager:GetResourcePolicy",
      "secretsmanager:DescribeSecret",
    ]
  }
}

# Fargate machine to machine secrets manager policy
resource "aws_iam_policy" "machine_to_machine_secret_policy" {
  name   = "SecretsManager-${var.environment}-ows-machine-to-machine-policy"
  policy = data.aws_iam_policy_document.machine_to_machine_secret_policy_document.json

  tags = {
    terraformed = true
    application_family = "devops"
  }
}

# Fargate python-orchard-features SPLITIO_API_KEY policy document
data "aws_iam_policy_document" "python_orchard_features_splitio_policy_document" {
  statement {
    effect = "Allow"

    resources = [
      "arn:aws:secretsmanager:*:*:secret:${var.environment}/python-orchard-features/SPLITIO_API_KEY*",
      "arn:aws:secretsmanager:*:*:secret:${var.environment}/python-orchard-features/SPLITIO_API_KEY",
    ]

    actions = [
      "secretsmanager:GetSecretValue",
      "kms:Decrypt",
    ]
  }
}

# Fargate python-orchard-features SPLITIO_API_KEY secret policy
resource "aws_iam_policy" "python_orchard_features_splitio_policy" {
  name   = "secretsmanager-${var.environment}-python-orchard-features-SPLITIO_API_KEY-ro"
  policy = data.aws_iam_policy_document.python_orchard_features_splitio_policy_document.json

  tags = {
    terraformed = true
    application_family = "devops"
  }
}

# Fargate  SPLITIO_API_KEY secret policy document
data "aws_iam_policy_document" "splitio_secret_policy_document" {
  statement {
    effect = "Allow"

    resources = [
      "arn:aws:secretsmanager:*:*:secret:${var.environment}/split/*",
      "arn:aws:secretsmanager:*:*:secret:${var.environment}/split/",
    ]

    actions = [
      "secretsmanager:ListSecretVersionIds",
      "secretsmanager:GetSecretValue",
      "secretsmanager:GetResourcePolicy",
      "secretsmanager:DescribeSecret",
    ]
  }

  statement {
    effect    = "Allow"
    resources = ["*"]
    actions   = ["secretsmanager:GetRandomPassword"]
  }
}

# Fargate SPLITIO_API_KEY secret policy
resource "aws_iam_policy" "splitio_secret_policy" {
  name   = "SecretsManager-${var.environment}-split-policy"
  policy = data.aws_iam_policy_document.splitio_secret_policy_document.json

  tags = {
    terraformed = true
    application_family = "devops"
  }
}

# Jenkins ecr user
resource "aws_iam_user" "jenkins-ecr-user" {
  name = "${var.environment}-jenkins-ecr"

  tags = {
    terraformed = true
    application_family = "devops"
  }
}

# Jenkins ecr user policy document
data "aws_iam_policy_document" "jenkins_ecr_user_policy_document" {
# checkov:skip=CKV_AWS_111:Silencing because this has constraints
  statement {
    effect    = "Allow"
    resources = ["*"]

    actions = [
      "ecr:Batch*",
      "ecr:CompleteLayerUpload",
      "ecr:Describe*",
      "ecr:Get*",
      "ecr:Get*",
      "ecr:GetAuthorizationToken",
      "ecr:InitiateLayerUpload",
      "ecr:List*",
      "ecr:PutImage",
      "ecr:UploadLayerPart",
    ]

    condition {
      test     = "IpAddress"
      variable = "aws:SourceIp"

      values = [
        "207.237.185.0/26",
        "208.91.130.128/25",
        "3.81.188.77/32",
        "3.213.73.88/32",
        "34.196.231.107/32",
        "52.202.238.54/32",
        "34.198.230.207/32",
        "3.213.93.225/32",
      ]
    }
  }
}

# Jenkins ecr user policy
resource "aws_iam_policy" "jenkins_ecr_user_policy" {
  name        = "ECR-${var.environment}-${var.service_name}-jenkins-policy"
  description = "Used in jenkin docker to ecr songwhip jobs"
  policy      = data.aws_iam_policy_document.jenkins_ecr_user_policy_document.json

  tags = {
    terraformed = true
    application_family = "devops"
  }
}

# Attach jenkins_ecr_user_policy to jenkins-ecr-user
resource "aws_iam_user_policy_attachment" "jenkins_ecr_user_policy_attachment" {
  user       = aws_iam_user.jenkins-ecr-user.name
  policy_arn = aws_iam_policy.jenkins_ecr_user_policy.arn
}

# Below this line is a temporary setup for SME security scanning


resource "aws_iam_policy" "sme_security_scanning" {
  name = "sme_security_scanning_policy"
  description = "sme_security_scanning_policy"
  policy = <<POLICY
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "apigateway:Get*",
                "a4b:Get*",
                "a4b:List*",
                "a4b:Search*",
                "access-analyzer:Get*",
                "access-analyzer:List*",
                "acm-pca:Describe*",
                "acm-pca:Get*",
                "acm-pca:List*",
                "acm:Describe*",
                "acm:Get*",
                "acm:List*",
                "airflow:List*",
                "amplify:Get*",
                "amplify:List*",
                "appconfig:Get*",
                "appconfig:List*",
                "application-autoscaling:Describe*",
                "autoscaling:Describe*",
                "applicationinsights:Describe*",
                "applicationinsights:List*",
                "appmesh:Describe*",
                "appmesh:List*",
                "appstream:Describe*",
                "appstream:List*",
                "appsync:Get*",
                "appsync:List*",
                "athena:Batch*",
                "athena:Get*",
                "athena:List*",
                "auditmanager:Get*",
                "auditmanager:List*",
                "batch:Describe*",
                "batch:List*",
                "budgets:Describe*",
                "budgets:View*",
                "cassandra:Select",
                "ce:Describe*",
                "ce:Get*",
                "ce:List*",
                "cloudfront:DescribeFunction",
                "cloudfront:Get*",
                "cloudfront:List*",
                "cloudhsm:Describe*",
                "cloudhsm:Get*",
                "cloudhsm:List*",
                "cloudsearch:Describe*",
                "cloudsearch:List*",
                "cloudwatch:Describe*",
                "cloudwatch:Get*",
                "cloudwatch:List*",
                "cognito-identity:Describe*",
                "cognito-identity:Get*",
                "cognito-identity:List*",
                "cognito-identity:Lookup*",
                "cognito-idp:AdminGet*",
                "cognito-idp:AdminList*",
                "cognito-idp:Describe*",
                "cognito-idp:Get*",
                "cognito-idp:List*",
                "cognito-sync:Describe*",
                "cognito-sync:Get*",
                "cognito-sync:List*",
                "cognito-sync:QueryRecords",
                "compute-optimizer:Describe*",
                "compute-optimizer:Get*",
                "datapipeline:Describe*",
                "datapipeline:Get*",
                "datapipeline:List*",
                "datapipeline:ValidatePipelineDefinition",
                "datapipeline:QueryObjects",
                "dynamodb:Describe*",
                "dynamodb:List*",
                "ec2:Describe*",
                "ec2:Get*",
                "ecr:Describe*",
                "ecr:ListImages",
                "ecs:Describe*",
                "ecs:List*",
                "eks:Describe*",
                "eks:List*",
                "elasticache:Describe*",
                "elasticache:List*",
                "elasticbeanstalk:Check*",
                "elasticbeanstalk:Describe*",
                "elasticbeanstalk:List*",
                "elasticbeanstalk:RequestEnvironmentInfo",
                "elasticfilesystem:Describe*",
                "elasticloadbalancing:Describe*",
                "elasticmapreduce:ListInstance*",
                "elastictranscoder:List*",
                "elastictranscoder:Read*",
                "es:GetCompatibleElasticsearchVersions",
                "es:GetUpgradeStatus",
                "es:ListElasticsearchInstanceTypeDetails",
                "es:Describe*",
                "es:List*",
                "events:Describe*",
                "events:List*",
                "glue:Get*",
                "glue:List*",
                "guardduty:Get*",
                "guardduty:List*",
                "health:Describe*",
                "iam:Get*",
                "iam:List*",
                "inspector:Describe*",
                "inspector:Get*",
                "inspector:List*",
                "inspector:Preview*",
                "kafka:Describe*",
                "kafka:Get*",
                "kafka:List*",
                "kinesis:Get*",
                "kinesis:List*",
                "kinesis:Describe*",
                "kms:Describe*",
                "kms:List*",
                "lambda:Get*",
                "lambda:List*",
                "logs:Describe*",
                "logs:Filter*",
                "logs:Get*",
                "macie2:Describe*",
                "macie2:Get*",
                "macie2:List*",
                "network-firewall:Describe*",
                "network-firewall:List*",
                "organizations:ListAccounts",
                "organizations:ListParents",
                "organizations:DescribeAccount",
                "rds:Describe*",
                "rds:List*",
                "route53:Get*",
                "route53:List*",
                "route53domains:Check*",
                "route53domains:Get*",
                "route53domains:List*",
                "route53domains:View*",
                "route53resolver:Get*",
                "route53resolver:List*",
                "s3:GetAccelerateConfiguration",
                "s3:GetAccessPoint*",
                "s3:GetAccountPublicAccessBlock",
                "s3:GetAnalyticsConfiguration",
                "s3:GetBucket*",
                "s3:GetEncryptionConfiguration",
                "s3:GetIntelligentTieringConfiguration",
                "s3:GetInventoryConfiguration",
                "s3:GetJobTagging",
                "s3:GetLifecycleConfiguration",
                "s3:GetMetricsConfiguration",
                "s3:GetMultiRegionAccess*",
                "s3:GetReplicationConfiguration",
                "s3:GetStorageLens*",
                "s3:List*",
                "secretsmanager:Describe*",
                "secretsmanager:GetResourcePolicy",
                "secretsmanager:List*",
                "securityhub:Describe*",
                "securityhub:Get*",
                "securityhub:List*",
                "serverlessrepo:Get*",
                "serverlessrepo:List*",
                "serverlessrepo:SearchApplications",
                "ses:Get*",
                "ses:List*",
                "shield:Describe*",
                "shield:Get*",
                "shield:List*",
                "sns:Get*",
                "sns:ListTopics",
                "sqs:Get*",
                "sqs:List*",
                "states:Describe*",
                "states:Get*",
                "states:List*",
                "swf:Describe*",
                "swf:Get*",
                "swf:List*",
                "tag:Get*",
                "waf-regional:Get*",
                "waf-regional:List*",
                "waf:Get*",
                "waf:List*",
                "wafv2:Describe*",
                "wafv2:Get*",
                "wafv2:List*",
                "wafv2:CheckCapacity",
                "xray:BatchGet*",
                "xray:Get*",
                "xray:List*",
                "cloudtrail:Describe*",
                "cloudtrail:Get*",
                "cloudtrail:List*",
                "config:BatchGetResourceConfig",
                "config:Deliver*",
                "config:Describe*",
                "config:Get*",
                "config:List*"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "apigateway:GET"
            ],
            "Resource": [
                "arn:aws:apigateway:*::/apis",
                "arn:aws:apigateway:*::/apis/*/routes",
                "arn:aws:apigateway:*::/apis/*/stages",
                "arn:aws:apigateway:*::/apis/*/stages/*",
                "arn:aws:apigateway:*::/clientcertificates/*",
                "arn:aws:apigateway:*::/restapis",
                "arn:aws:apigateway:*::/restapis/*/authorizers",
                "arn:aws:apigateway:*::/restapis/*/authorizers/*",
                "arn:aws:apigateway:*::/restapis/*/documentation/versions",
                "arn:aws:apigateway:*::/restapis/*/resources",
                "arn:aws:apigateway:*::/restapis/*/resources/*",
                "arn:aws:apigateway:*::/restapis/*/resources/*/methods/*",
                "arn:aws:apigateway:*::/restapis/*/stages",
                "arn:aws:apigateway:*::/restapis/*/stages/*",
                "arn:aws:apigateway:*::/tags/*",
                "arn:aws:apigateway:*::/vpclinks"
            ]
        }
    ]
}
POLICY
}

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

    principals {
      type = "AWS"

      identifiers = [
        "arn:aws:iam::943540511943:role/ReadOnlyInfoSec",
      ]
    }

    condition {
      test     = "StringEquals"
      values   = ["v2aFHqPL28L3QCx0cN5Hvv0f4ff4p0FUyuvZaPoT/Qo="]
      variable = "sts:ExternalId"
    }
  }
}

# Jenkins pipeline agents will assume this role in order to run deploys.
resource "aws_iam_role" "sme_security_deploy_role" {
  name               = "sme_security_role"
  assume_role_policy = data.aws_iam_policy_document.sme_security_assume_role_policy.json
}

resource "aws_iam_role_policy_attachment" "sme_security_role_policy_attachment" {
  policy_arn = aws_iam_policy.sme_security_scanning.arn
  role       = aws_iam_role.sme_security_deploy_role.id
}

module "ecs_infrastructure_role" {
  source = "git@github.com:theorchard/terraform-iam-policies.git//modules/ecs-infrastructure-role?ref=1.22.4"
}
