provider "google" {
}

variable gcp_project_id {
  description = "Enter your Google Cloud Platform Project ID (it tends to be a hyphenated string)"
}

variable account_name {
  description = "Enter a username for the new Service Account"
}

variable "aws_account_id" {
  type    = string
  default = "995163501499"
}

variable "gcp_roles" {
  description = "The roles that the Service Account can access. Recommend only appending to these roles."
  default = ["roles/iam.serviceAccountTokenCreator", "roles/browser", "roles/compute.viewer"]
}

data "google_project" "main" {
  project_id = var.gcp_project_id
}

# Enable necessary API
resource "google_project_service" "iamcredentials" {
  project = var.gcp_project_id
  service = "iamcredentials.googleapis.com"
}

resource "google_project_service" "sts" {
  project = var.gcp_project_id
  service = "sts.googleapis.com"
}

# Create Workload Identity Pool
resource "google_iam_workload_identity_pool" "aws_pool" {
  project  = var.gcp_project_id
  display_name = "Identity Pool for tfstate"
  description = "To allow tfstate.com to run scans"
  workload_identity_pool_id = "pool-for-${var.account_name}"
}

# Create Workload Identity Provider
resource "google_iam_workload_identity_pool_provider" "aws_provider" {
  project                            = var.gcp_project_id
  workload_identity_pool_id          = google_iam_workload_identity_pool.aws_pool.workload_identity_pool_id
  workload_identity_pool_provider_id = "pool-provider-tfstate"
  display_name                       = "AWS to GCP for tfstate"
  aws {
    account_id = var.aws_account_id
  }
  attribute_mapping = {
    "google.subject"        = "assertion.arn"
    "attribute.aws_role"    = "assertion.arn"
  }
  attribute_condition = "assertion.arn.startsWith('arn:aws:sts::${var.aws_account_id}:assumed-role/tfstate')"
}

resource "google_service_account" "main" {
  project      = var.gcp_project_id
  account_id   = var.account_name
  display_name = "tfstate.com Service Account"
  description  = "Service account to allow tfstate.com to run scans"
}

# Allow the AWS role to impersonate the Google service account
resource "google_service_account_iam_binding" "aws_sa_impersonation" {
  service_account_id = google_service_account.main.name
  role               = "roles/iam.workloadIdentityUser"
  members = [
    "principalSet://iam.googleapis.com/${google_iam_workload_identity_pool.aws_pool.name}/attribute.aws_role/arn:aws:sts::${var.aws_account_id}:assumed-role/tfstate-infra/tfstate-infra",
    "principalSet://iam.googleapis.com/${google_iam_workload_identity_pool.aws_pool.name}/attribute.aws_role/arn:aws:sts::${var.aws_account_id}:assumed-role/tfstate-scan/tfstate-scan"
  ]
}

# Assign roles to the Service Account
resource "google_project_iam_member" "main" {
  for_each = toset(var.gcp_roles)
  project = var.gcp_project_id
  role    = each.value
  member  = "serviceAccount:${google_service_account.main.email}"
}

# terraform output -raw service_account_credentials_json to get json
output "service_account_credentials_json" {
  value = jsonencode({
    universe_domain = "googleapis.com",
    type = "external_account",
    audience = "//iam.googleapis.com/projects/${data.google_project.main.number}/locations/global/workloadIdentityPools/${google_iam_workload_identity_pool.aws_pool.workload_identity_pool_id}/providers/${google_iam_workload_identity_pool_provider.aws_provider.workload_identity_pool_provider_id}",
    subject_token_type = "urn:ietf:params:aws:token-type:aws4_request",
    service_account_impersonation_url = "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/${google_service_account.main.email}:generateAccessToken",
    token_url = "https://sts.googleapis.com/v1/token",
    credential_source = {
      environment_id = "aws1",
      region_url = "http://169.254.169.254/latest/meta-data/placement/availability-zone",
      url = "http://169.254.169.254/latest/meta-data/iam/security-credentials",
      regional_cred_verification_url = "https://sts.ap-southeast-2.amazonaws.com?Action=GetCallerIdentity&Version=2011-06-15"
    }
  })
}
