locals {
  account_id = data.aws_caller_identity.current.account_id
}

data "aws_caller_identity" "current" {}

module "kms_policy" {
  source                 = "./kms_policy"
  account_id             = local.account_id
  allowed_admin_accounts = var.allowed_accounts
  allowed_admin_roles    = var.allowed_roles
}

resource "aws_kms_key" "terraform" {
  description         = "KMS key for terraform bucket."
  enable_key_rotation = true
  tags                = var.common_tags
  policy              = module.kms_policy.kms_policy_json
}

resource "aws_kms_alias" "secrets_serviceonly_alias" {
  name          = "alias/terraform"
  target_key_id = aws_kms_key.terraform.key_id
}

module "default_logs_bucket_policy" {
  source              = "../s3/bucket_policies/default_policy_template"
  template_bucket_arn = "arn:aws:s3:::security-${local.account_id}-logs"
}

data "aws_iam_policy_document" "logs" {
  source_policy_documents = [module.default_logs_bucket_policy.document.json]
  statement {
    effect = "Allow"
    principals {
      type        = "AWS"
      identifiers = ["arn:aws:iam::${var.aws_elb_account_id}:root"]
    }
    actions   = ["s3:PutObject"]
    resources = ["arn:aws:s3:::security-${local.account_id}-logs/elb/*"]
  }
  statement {
    sid    = "AWSLogDeliveryWrite"
    effect = "Allow"
    principals {
      identifiers = ["delivery.logs.amazonaws.com"]
      type        = "Service"
    }
    actions   = ["s3:PutObject"]
    resources = ["arn:aws:s3:::security-${local.account_id}-logs/vpcflow/AWSLogs/${local.account_id}/*"]
    condition {
      test     = "StringEquals"
      values   = ["bucket-owner-full-control"]
      variable = "s3:x-amz-acl"
    }
    condition {
      test     = "StringEquals"
      values   = [local.account_id]
      variable = "aws:SourceAccount"
    }
  }
  statement {
    sid    = "AWSLogDeliveryCheck"
    effect = "Allow"
    principals {
      identifiers = ["delivery.logs.amazonaws.com"]
      type        = "Service"
    }
    actions   = ["s3:GetBucketAcl", "s3:ListBucket"]
    resources = ["arn:aws:s3:::security-${local.account_id}-logs"]
    condition {
      test     = "StringEquals"
      values   = [local.account_id]
      variable = "aws:SourceAccount"
    }
  }
  statement {
    effect = "Allow"
    principals {
      type        = "Service"
      identifiers = ["guardduty.amazonaws.com"]
    }
    actions   = ["s3:GetBucketLocation"]
    resources = ["arn:aws:s3:::security-${local.account_id}-logs"]
  }
  statement {
    effect = "Allow"
    principals {
      type        = "Service"
      identifiers = ["guardduty.amazonaws.com"]
    }
    actions   = ["s3:PutObject"]
    resources = ["arn:aws:s3:::security-${local.account_id}-logs/gd/*"]
    condition {
      test     = "StringEquals"
      variable = "s3:x-amz-server-side-encryption"
      values   = ["aws:kms"]
    }
  }
  statement {
    sid    = "S3ServerAccessLogsPolicy"
    effect = "Allow"
    principals {
      type        = "Service"
      identifiers = ["logging.s3.amazonaws.com"]
    }
    actions   = ["s3:PutObject"]
    resources = ["arn:aws:s3:::security-${local.account_id}-logs/s3/*"]
    condition {
      test     = "StringEquals"
      variable = "aws:SourceAccount"
      values   = [local.account_id]
    }
  }
}

resource "aws_s3_bucket" "logs" {
  bucket = "security-${local.account_id}-logs"
  tags   = var.common_tags
}

resource "aws_s3_bucket_acl" "logs" {
  bucket = aws_s3_bucket.logs.id
  acl    = "private"
}

resource "aws_s3_bucket_policy" "logs" {
  # https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html
  bucket = aws_s3_bucket.logs.id
  policy = data.aws_iam_policy_document.logs.json
}

resource "aws_s3_bucket_server_side_encryption_configuration" "logs" {
  bucket = aws_s3_bucket.logs.id
  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
    }
  }
}

resource "aws_s3_bucket_lifecycle_configuration" "logs" {
  bucket = aws_s3_bucket.logs.id
  rule {
    id     = "${var.name_prefix}-logs"
    status = "Enabled"

    expiration {
      days = var.expiration_days_number
    }
  }
}

resource "aws_s3_bucket_public_access_block" "logs" {
  bucket = aws_s3_bucket.logs.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

# Tfstate bucket
module "default_tfstate_bucket_policy" {
  source              = "../s3/bucket_policies/default_policy_template"
  template_bucket_arn = aws_s3_bucket.tf_state_bucket.arn
}

resource "aws_s3_bucket" "tf_state_bucket" {
  bucket = "${var.name_prefix}-tfstate"
  tags   = var.common_tags
}

resource "aws_s3_bucket_acl" "tfstate" {
  bucket = aws_s3_bucket.tf_state_bucket.id
  acl    = "private"
}

resource "aws_s3_bucket_ownership_controls" "tfstate" {
  bucket = aws_s3_bucket.tf_state_bucket.id

  rule {
    object_ownership = "BucketOwnerEnforced"
  }
}

resource "aws_s3_bucket_policy" "tfstate" {
  bucket = aws_s3_bucket.tf_state_bucket.id
  policy = module.default_tfstate_bucket_policy.document.json
}

resource "aws_s3_bucket_server_side_encryption_configuration" "tfstate" {
  bucket = aws_s3_bucket.tf_state_bucket.id
  rule {
    apply_server_side_encryption_by_default {
      kms_master_key_id = aws_kms_key.terraform.arn
      sse_algorithm     = "aws:kms"
    }
  }
}

resource "aws_s3_bucket_lifecycle_configuration" "tfstate" {
  bucket = aws_s3_bucket.tf_state_bucket.id
  rule {
    id     = "Expiration for non current versions"
    status = "Enabled"

    abort_incomplete_multipart_upload {
      days_after_initiation = 7
    }

    noncurrent_version_expiration {
      noncurrent_days = var.tf_s3_noncurrent_version_expiration
    }
  }
}

resource "aws_s3_bucket_versioning" "tfstate" {
  bucket = aws_s3_bucket.tf_state_bucket.id

  versioning_configuration {
    status = "Enabled"
  }
}

resource "aws_s3_bucket_logging" "tfstate" {
  bucket        = aws_s3_bucket.tf_state_bucket.id
  target_bucket = aws_s3_bucket.logs.id
  target_prefix = "s3/${var.env_prefix}-tfsate/"
}

resource "aws_s3_bucket_public_access_block" "tfstate" {
  bucket = aws_s3_bucket.tf_state_bucket.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}
