Skip to content

Commit f79fae6

Browse files
yeshwanth1993Yeshwanth Gunasekarangemini-code-assist[bot]
authored
Terraform Skill (#86)
* Terraform Skill * Add references * Update skills/gcp-terraform/SKILL.md Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Update skills/gcp-terraform/SKILL.md Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --------- Co-authored-by: Yeshwanth Gunasekaran <yesh@google.com> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
1 parent 658ae0b commit f79fae6

7 files changed

Lines changed: 467 additions & 0 deletions

File tree

skills/gcp-terraform/SKILL.md

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
---
2+
name: terraform-gcp-skill
3+
description: "Architect, provision, and troubleshoot production-grade Google Cloud infrastructure using Terraform and OpenTofu. Use to design landing zones (Shared VPCs, Folders), deploy core services (GKE, Cloud Run, Cloud SQL), implement IAM least-privilege, and manage GCS-backed state. Enforces Google’s Cloud Foundation Fabric patterns and rigorous validation protocols to ensure secure, idempotent, and scalable deployments across environments."
4+
version: "1.0.0"
5+
---
6+
7+
# Terraform GCP Skill
8+
9+
This skill provides expert-level guidance for architecting, deploying, and managing GCP infrastructure using Terraform.
10+
11+
## 🎯 When to Use This Skill
12+
- Designing GCP Landing Zones (Projects, Folders, Shared VPCs).
13+
- Provisioning Google Cloud resources (GKE, Cloud Run, Cloud SQL, Spanner).
14+
- Setting up remote state management via **GCS Backend**.
15+
- Implementing IAM least-privilege via Terraform.
16+
- Troubleshooting `terraform plan` discrepancies in GCP.
17+
18+
## 🏗️ Core Architecture: GCS Backend & State
19+
**Always** use a GCS backend for state. Local state is strictly for local prototyping and must never be committed.
20+
21+
### Standard Backend Configuration
22+
```hcl
23+
terraform {
24+
backend "gcs" {
25+
bucket = "tf-state-${var.project_id}"
26+
prefix = "terraform/state/${var.environment}"
27+
}
28+
}
29+
```
30+
31+
Note: The GCS bucket must have Object Versioning enabled to allow recovery from accidental state corruption or overlapping writes.
32+
33+
## 🛠️ Execution Protocol (Safety First)
34+
The Agent must follow this lifecycle for every infrastructure change to ensure idempotency and prevent production outages:
35+
36+
1. Initialize (`terraform init`):
37+
38+
- Verify backend connectivity.
39+
40+
- Ensure provider plugins are downloaded and versions are locked in `.terraform.lock.hcl`.
41+
42+
2. Validate (`terraform validate` & `tflint`):
43+
44+
- Check for internal HCL consistency.
45+
46+
- Run `tflint` with the Google plugin to catch cloud-specific deprecated fields or non-optimal configurations.
47+
48+
3. Plan (`terraform plan -out=tfplan`):
49+
50+
- Generate a speculative execution plan.
51+
52+
- Mandatory Step: The Agent must summarize the plan for the user, specifically highlighting any Destroy actions.
53+
54+
4. Apply (`terraform apply tfplan`):
55+
56+
- Strict Constraint: Only execute the application after the user provides explicit manual confirmation.
57+
58+
## 🔍 Live Provider Documentation Lookup
59+
To prevent hallucinations regarding new fields or deprecated attributes, the Agent must verify the grounded truth of the provider schema.
60+
61+
Schema Inspection via CLI
62+
The primary command for retrieving the machine-readable schema of the currently initialized providers is:
63+
64+
```bash
65+
$ terraform providers schema -json
66+
```
67+
68+
69+
## 🛡️ GCP-Specific Standards
70+
1. Resource Naming & "Main" Pattern
71+
To maintain a clean module interface, use the main identifier for singleton resources (the primary resource the module is named after). Use underscores for identifiers and hyphens for names.
72+
73+
```hcl
74+
resource "google_compute_network" "main" {
75+
name = "${var.prefix}-vpc"
76+
auto_create_subnetworks = false
77+
}
78+
```
79+
80+
2. IAM Management
81+
- Avoid google_project_iam_policy: This resource is authoritative and replaces the entire IAM policy for the project. It is the #1 cause of accidental lockouts.
82+
- Avoid `google_project_iam_policy`: This resource is authoritative for the entire project and is a common cause of accidental lockouts.
83+
84+
- Prefer `google_project_iam_member` or `google_project_iam_binding`:
85+
- `google_project_iam_member` is additive and safely grants a role to a single member.
86+
- `google_project_iam_binding` is authoritative for a single role. It's useful for managing all members of a role, but be aware it overwrites existing members for that role.
87+
- Shared VPC: Always distinguish between Host projects (where the network lives) and Service projects (where resources consume the network).
88+
- Private Google Access: Subnets should always have private_ip_google_access = true.
89+
- Workload Identity: Prefer GKE Workload Identity over static Service Account JSON keys.
90+
91+
## 📂 Directory Structure
92+
Follow this standard to ensure compatibility with Antigravity (AGY) discovery and Google best practices:
93+
94+
```
95+
.
96+
├── main.tf # Entry point / Resource definitions
97+
├── variables.tf # Typed variables with units and descriptions
98+
├── outputs.tf # Resource ID outputs (no direct input pass-through)
99+
├── versions.tf # Provider version pinning
100+
├── network.tf # (Optional) Grouped networking resources
101+
├── examples/ # Example usage for modules
102+
├── files/ # Static files (startup scripts, etc.)
103+
├── templates/ # .tftpl templates
104+
├── scripts/ # Scripts called by Terraform
105+
└── helpers/ # Scripts NOT called by Terraform
106+
```
107+
## ⚠️ Anti-Patterns (Do NOT do these)
108+
- ❌ Hardcoded IDs: Never hardcode Project IDs. Use variables or data "google_project" sources.
109+
110+
- ❌ Service Account Keys: Never generate or store .json keys. Use Workload Identity Federation or the default metadata server.
111+
112+
- ❌ Hardcoded IDs: Never hardcode Project IDs. Use variables or a `data "google_project"` source.
113+
114+
- ❌ Broad Scopes: Avoid cloud-platform scopes for GKE nodes; use fine-grained IAM roles instead.
115+
116+
## 🧪 Testing Strategy
117+
- Static Analysis: Use checkov, trivy, or terrascan to catch insecure GCP configurations (e.g., public GCS buckets).
118+
119+
- Integration Testing: Use terraform test (v1.6+) to assert that GCP labels and network tags are correctly applied to resources before full deployment.
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# GCP Networking Patterns
2+
3+
GCP's global VPC architecture requires specific patterns for Shared VPCs, Private Access, and Security Perimeters.
4+
5+
## 🤝 Shared VPC Configuration
6+
In a Shared VPC topology, distinguish clearly between the **Host Project** (manages the network) and the **Service Project** (hosts resources like GKE or VMs).
7+
8+
### 1. Enabling the Host Project
9+
```hcl
10+
resource "google_compute_shared_vpc_host_project" "host" {
11+
project = var.host_project_id
12+
}
13+
```
14+
15+
### 2. Attaching a Service Project
16+
```hcl
17+
resource "google_compute_shared_vpc_service_project" "service" {
18+
host_project = google_compute_shared_vpc_host_project.host.project
19+
service_project = var.service_project_id
20+
}
21+
```
22+
23+
## 🔒 Private Service Access (PSA)
24+
Required for connecting to managed services like Cloud SQL or Redis via internal IP addresses.
25+
26+
```hcl
27+
# 1. Reserve an internal IP range
28+
resource "google_compute_global_address" "private_ip_alloc" {
29+
name = "google-managed-services-range"
30+
purpose = "VPC_PEERING"
31+
address_type = "INTERNAL"
32+
prefix_length = 16
33+
network = google_compute_network.this.id
34+
}
35+
36+
# 2. Establish the peering connection
37+
resource "google_service_networking_connection" "private_vpc_connection" {
38+
network = google_compute_network.this.id
39+
service = "servicenetworking.googleapis.com"
40+
reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name]
41+
}
42+
```
43+
44+
## 🛡️ VPC Service Controls (VPC-SC)
45+
VPC-SC perimeters protect data in services like GCS and BigQuery. Ensure Terraform has the necessary `access_context_manager` permissions to modify perimeters.
46+
47+
```hcl
48+
resource "google_access_context_manager_service_perimeter" "perimeter" {
49+
parent = "accessPolicies/${var.access_policy_id}"
50+
name = "accessPolicies/${var.access_policy_id}/servicePerimeters/${var.perimeter_name}"
51+
title = var.perimeter_name
52+
53+
status {
54+
restricted_services = ["storage.googleapis.com", "bigquery.googleapis.com"]
55+
resources = ["projects/${var.project_number}"]
56+
57+
access_levels = [google_access_context_manager_access_level.this.name]
58+
}
59+
}
60+
```
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# IAM and Security Standards for GCP
2+
3+
Prevent outages and security breaches by following additive IAM patterns and leveraging Workload Identity.
4+
5+
## 🚫 Additive vs. Authoritative IAM
6+
**NEVER** use authoritative resources (`google_project_iam_policy` or `google_project_iam_binding`) for core projects unless you are explicitly managing the *entire* policy and understand the risk of lockouts.
7+
8+
| Resource | Type | Impact | Usage |
9+
| :--- | :--- | :--- | :--- |
10+
| `google_project_iam_member` | **Additive** | Adds a single member/role. Safe. | **Preferred** |
11+
| `google_project_iam_binding` | **Authoritative (Role)** | Overwrites all members for a specific role. | Use with caution. |
12+
| `google_project_iam_policy` | **Authoritative (Project)** | Overwrites the entire project IAM policy. | **BANNED** for general use. |
13+
14+
### Example: Safe Additive IAM
15+
```hcl
16+
resource "google_project_iam_member" "storage_admin" {
17+
project = var.project_id
18+
role = "roles/storage.admin"
19+
member = "serviceAccount:${google_service_account.this.email}"
20+
}
21+
```
22+
23+
## 🆔 Workload Identity (GKE)
24+
Bind Kubernetes Service Accounts (KSA) to Google Service Accounts (GSA) without managing JSON keys.
25+
26+
```hcl
27+
# 1. The Google Service Account
28+
resource "google_service_account" "gsa" {
29+
account_id = "app-workload-sa"
30+
project = var.project_id
31+
}
32+
33+
# 2. The IAM Binding for Workload Identity
34+
resource "google_project_iam_member" "workload_identity_user" {
35+
project = var.project_id
36+
role = "roles/iam.workloadIdentityUser"
37+
member = "serviceAccount:${var.project_id}.svc.id.goog[${var.k8s_namespace}/${var.k8s_sa_name}]"
38+
}
39+
```
40+
41+
## 🏛️ Organization Policy Constraints
42+
Common constraints to enforce during `terraform validate` or `plan`:
43+
44+
- `constraints/compute.disableSerialPortAccess`: Prevents unencrypted console access.
45+
- `constraints/compute.vmExternalIpAccess`: Blocks external IPs for VMs.
46+
- `constraints/iam.allowedPolicyMemberDomains`: Restricts IAM to specific Workspace/Cloud Identity domains.
47+
48+
```hcl
49+
resource "google_project_organization_policy" "disable_serial_port" {
50+
project = var.project_id
51+
constraint = "constraints/compute.disableSerialPortAccess"
52+
53+
boolean_policy {
54+
enforced = true
55+
}
56+
}
57+
```
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# GCP Naming Conventions for Terraform
2+
3+
Standardizing resource names ensures compatibility with GCP's heterogeneous naming requirements and maintains consistency across environments.
4+
5+
## 🏗️ Core Principles
6+
1. **Lowercase Only**: Most GCP resources (GCE, GCS, GKE) require lowercase alphanumeric characters and hyphens.
7+
2. **DNS Compliance (RFC 1035)**: Names must start with a letter, end with a letter or digit, and use only `-` (no underscores).
8+
3. **Object Naming (Underscores)**: Name all configuration objects (resource/data source identifiers) using **underscores**.
9+
4. **Resource Names (Hyphens)**: Use **hyphens** for the actual resource names within GCP.
10+
11+
Recommended:
12+
```hcl
13+
resource "google_compute_instance" "web_server" {
14+
name = "web-server"
15+
}
16+
```
17+
18+
## 📌 Resource-Specific Rules
19+
20+
| Resource Type | Regex Pattern | Max Length | Notes |
21+
| :--- | :--- | :--- | :--- |
22+
| `google_compute_instance` | `^[a-z]([-a-z0-9]*[a-z0-9])?$` | 63 | RFC 1035 compliant. |
23+
| `google_storage_bucket` | `^[a-z0-9][a-z0-9._-]{1,61}[a-z0-9]$` | 63 | Global namespace; no underscores. |
24+
| `google_project` | `^[a-z][a-z0-9-]{4,28}[a-z0-9]$` | 30 | Must be globally unique. |
25+
26+
## 🧩 The Singleton Pattern (`main`)
27+
To simplify references to a resource that is the only one of its type in a module, name the identifier `main`.
28+
29+
- **Keep it singular**: Resource names should be singular.
30+
- **No redundancy**: Don't repeat the resource type in the identifier.
31+
32+
Recommended:
33+
```hcl
34+
resource "google_compute_network" "main" {
35+
name = "${var.prefix}-${var.environment}-vpc"
36+
}
37+
```
38+
39+
Not Recommended:
40+
```hcl
41+
resource "google_compute_network" "main_vpc" { ... }
42+
```
43+
44+
## 🌍 Multi-Environment Prefixing
45+
Always use a prefixing logic to prevent collisions and identify ownership.
46+
47+
```hcl
48+
variable "prefix" {
49+
type = string
50+
description = "Project or team prefix (e.g., 'acme')"
51+
}
52+
53+
variable "environment" {
54+
type = string
55+
description = "Target environment (e.g., 'prod', 'staging')"
56+
}
57+
58+
# Implementation
59+
resource "google_service_account" "app_sa" {
60+
account_id = "${var.prefix}-${var.environment}-app"
61+
display_name = "Application Service Account for ${var.environment}"
62+
}
63+
```
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Terraform Style and Structure Best Practices
2+
3+
This document outlines the standard style and directory structure for GCP Terraform configurations, ensuring they are maintainable, readable, and follow Google Cloud's recommended patterns.
4+
5+
## 📂 Standard Module Structure
6+
Follow this layout for both reusable modules and root configurations:
7+
8+
- `main.tf`: Default location for resources.
9+
- `variables.tf`: All variable declarations with types and descriptions.
10+
- `outputs.tf`: All output declarations with descriptions.
11+
- `README.md`: Module documentation (use `terraform-docs` for automation).
12+
- `examples/`: Subdirectories for each usage example with their own READMEs.
13+
- `scripts/`: Custom scripts called by Terraform provisioners.
14+
- `helpers/`: Scripts not called by Terraform.
15+
- `files/`: Static files (e.g., startup scripts).
16+
- `templates/`: Template files (use `.tftpl` extension).
17+
- `docs/`: Additional long-form documentation.
18+
19+
### Logical Grouping
20+
Group resources by shared purpose rather than giving every resource its own file.
21+
- `network.tf`: VPCs, subnets, firewall rules.
22+
- `instances.tf`: Compute Engine VMs, Managed Instance Groups.
23+
- `iam.tf`: Service accounts and IAM bindings.
24+
25+
## 🔢 Variables and Outputs
26+
27+
### Variables
28+
- **Units in Names**: Include units for numeric values (e.g., `ram_size_gb`, `disk_size_mib`).
29+
- **Binary vs Decimal**: Use binary prefixes (KiB, MiB, GiB) for storage and decimal (KB, MB, GB) for other measurements.
30+
- **Positive Booleans**: Name booleans positively (e.g., `enable_external_access` instead of `disable_internal_only`).
31+
- **Mandatory Descriptions**: All variables must have `description` and `type`.
32+
- **Default Values**: Provide defaults for environment-independent values; omit them for environment-specific values (like `project_id`) to force explicit input.
33+
34+
### Outputs
35+
- **Resource Attributes**: Always reference resource attributes in outputs, not input variables, to preserve the dependency graph.
36+
- **Descriptions**: All outputs must have a `description`.
37+
38+
## 🛠️ Logic and Complexity
39+
- **Formatting**: Always run `terraform fmt`.
40+
- **Ternaries**: Never use more than one ternary operator on a single line.
41+
- **Complexity**: Split complex interpolated expressions into multiple `local` values.
42+
- **Count vs For Each**:
43+
- Use `count` for conditional resource creation.
44+
- Use `for_each` for multiple instances of a resource based on a map or set.
45+
46+
## 🔒 State Preservation
47+
For stateful resources (Cloud SQL, Spanner, etc.), always enable deletion protection.
48+
49+
```hcl
50+
resource "google_sql_database_instance" "main" {
51+
name = "primary-instance"
52+
database_version = "POSTGRES_15"
53+
54+
settings {
55+
tier = "db-f1-micro"
56+
}
57+
58+
deletion_protection = true
59+
60+
lifecycle {
61+
prevent_destroy = true
62+
}
63+
}
64+
```

0 commit comments

Comments
 (0)