# terraform/workload_identity.tf
#
# DPDPA Zero Trust — Identity Pillar (GCP Workload Identity Federation)
# Legal basis: DPDP Rules 2025, Rule 6(1)(b)
#   "appropriate measures to control access to the computer resources used by
#    such Data Fiduciary or such a Data Processor, wherever applicable"
# Least-privilege bindings are the engineering reading of "appropriate".
#
# This configuration:
#   1. Creates a Workload Identity Pool for Kubernetes workloads
#   2. Creates a provider that maps k8s service account tokens → GCP identities
#   3. Creates a least-privilege service account for personal-data reads
#   4. Binds the Workload Identity membership with a conditional attribute mapping
#
# Principle of least privilege is enforced at three layers:
#   - IAM role (roles/cloudsql.client — read-only, not admin)
#   - Attribute condition (only the named k8s namespace/SA can impersonate)
#   - Workload Identity Pool (scoped to this project, not org-wide)

terraform {
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "~> 5.0"
    }
  }
}

variable "project_id" {
  description = "GCP project ID containing personal data systems"
  type        = string
}

variable "kubernetes_namespace" {
  description = "Kubernetes namespace of the workload accessing personal data"
  type        = string
  default     = "personal-data-svc"
}

variable "kubernetes_service_account" {
  description = "Kubernetes service account name of the workload"
  type        = string
  default     = "pii-reader"
}

# ---------------------------------------------------------------------------
# Workload Identity Pool
# Scoped to this project — no cross-project impersonation possible
# ---------------------------------------------------------------------------
resource "google_iam_workload_identity_pool" "dpdpa_zt_pool" {
  project                   = var.project_id
  workload_identity_pool_id = "dpdpa-zt-pool"
  display_name              = "DPDPA Zero Trust Pool"
  description               = "Workload Identity Pool for DPDPA Rule 6(1)(b) least-privilege access"
}

# ---------------------------------------------------------------------------
# OIDC Provider — maps Kubernetes service account tokens
# ---------------------------------------------------------------------------
resource "google_iam_workload_identity_pool_provider" "k8s_provider" {
  project                            = var.project_id
  workload_identity_pool_id          = google_iam_workload_identity_pool.dpdpa_zt_pool.workload_identity_pool_id
  workload_identity_pool_provider_id = "k8s-provider"
  display_name                       = "Kubernetes OIDC Provider"

  # Attribute mapping: extract k8s namespace and service account from the token
  attribute_mapping = {
    "google.subject"       = "assertion.sub"
    "attribute.namespace"  = "assertion['kubernetes.io']['namespace']"
    "attribute.sa_name"    = "assertion['kubernetes.io']['serviceaccount']['name']"
  }

  # Only tokens from the approved namespace/SA combination are accepted
  attribute_condition = "attribute.namespace == '${var.kubernetes_namespace}' && attribute.sa_name == '${var.kubernetes_service_account}'"

  oidc {
    # Replace with your cluster's OIDC issuer URL
    issuer_uri = "https://container.googleapis.com/v1/projects/${var.project_id}/locations/asia-south1/clusters/pii-cluster"
  }
}

# ---------------------------------------------------------------------------
# Least-privilege GCP Service Account
# roles/cloudsql.client — can connect to Cloud SQL but cannot administer it
# ---------------------------------------------------------------------------
resource "google_service_account" "pii_reader" {
  project      = var.project_id
  account_id   = "pii-reader-sa"
  display_name = "PII Reader Service Account (DPDPA Rule 6(1)(b))"
  description  = "Least-privilege SA: read-only access to personal data Cloud SQL instance"
}

# Bind the Workload Identity member to the SA
resource "google_service_account_iam_member" "wif_binding" {
  service_account_id = google_service_account.pii_reader.name
  role               = "roles/iam.workloadIdentityUser"
  member = "principalSet://iam.googleapis.com/${google_iam_workload_identity_pool.dpdpa_zt_pool.name}/attribute.namespace/${var.kubernetes_namespace}"
}

# Grant only Cloud SQL client role — not editor, not admin
resource "google_project_iam_member" "cloudsql_client" {
  project = var.project_id
  role    = "roles/cloudsql.client"
  member  = "serviceAccount:${google_service_account.pii_reader.email}"
}

# ---------------------------------------------------------------------------
# Outputs
# ---------------------------------------------------------------------------
output "workload_identity_pool_id" {
  value       = google_iam_workload_identity_pool.dpdpa_zt_pool.id
  description = "Pool ID for use in k8s SA annotation"
}

output "pii_reader_sa_email" {
  value       = google_service_account.pii_reader.email
  description = "Service account email with least-privilege Cloud SQL access"
}

output "workload_identity_provider" {
  value       = google_iam_workload_identity_pool_provider.k8s_provider.name
  description = "Full provider resource name for GKE configuration"
}
