AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Iac Generator

skill-tahirraufkeeyu-software-development-agent-stack-sdas-iac-generator · by tahirraufkeeyu

Use when provisioning or modifying cloud infrastructure as code. Generates Terraform (HCL), Bicep, or Pulumi code for common resources (AKS/EKS, RDS, S3, VNet/VPC, IAM) with remote state, encryption, and least-privilege defaults.

— No reviews yet
0 installs
37 views
0.0% view→install

Install

$ agentstack add skill-tahirraufkeeyu-software-development-agent-stack-sdas-iac-generator

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • ✓ Prompt-injection patterns
  • ✓ Secret / credential exfiltration
  • ✓ Dangerous shell & filesystem operations
  • ✓ Untrusted network calls
  • ✓ Known-malicious package signatures

What it can access

  • ✓ Network access No
  • ✓ Filesystem access No
  • ✓ Shell / process execution No
  • ● Environment & secrets Used
  • ✓ Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-tahirraufkeeyu-software-development-agent-stack-sdas-iac-generator)

Reliability & compatibility

✓ Security review passed
0 installs to date
— no reviews yet
○ 5mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Iac Generator? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

When to use

  • Standing up a new environment (dev/staging/prod) from scratch.
  • Adding a specific resource (cluster, database, bucket, network) to an existing stack.
  • Converting click-ops resources into code after drift is detected.
  • Producing a reference module that application teams can call from their own stacks.

Do not use for one-off console experimentation or for rendering architecture diagrams.

Inputs

  • tool — terraform | bicep | pulumi (Python or TypeScript).
  • cloud — aws | azure | gcp.
  • resources — list of components to generate, from:
  • Cluster: aks, eks, gke.
  • Database: rds-postgres, azure-postgres-flexible, cloud-sql-postgres.
  • Object storage: s3, azure-storage, gcs.
  • Network: vpc, vnet (with public/private subnets + NAT + flow logs).
  • Identity: iam-role-least-privilege with service-to-service bindings.
  • env — dev | staging | prod (controls sizing, backup retention, deletion protection).
  • region — primary region; optional secondary_region for DR.
  • name_prefix — organization/project prefix used in naming (e.g. acme-checkout).
  • tags — mandatory tags map (Owner, Env, CostCenter, ManagedBy=terraform).
  • state_backend — details for remote state (bucket/container/lock table).

Outputs

  • Module directory layout under infrastructure/// with main.tf / main.bicep / __main__.py plus variables, outputs, and README.md.
  • Remote state configuration (backend.tf, providers.tf, or Pulumi Pulumi..yaml).
  • .checkov.yaml / tflint.hcl / psrule.yaml policy configs.
  • A make plan target and CI integration notes.

Tool dependencies

  • terraform >= 1.7, tflint, checkov, terraform-docs.
  • az, bicep CLI >= 0.30 for Bicep; PSRule.Rules.Azure for policy.
  • pulumi CLI for Pulumi; @pulumi/policy for policy-as-code.
  • Cloud CLI for the target provider (aws, az, gcloud).
  • jq for parsing plan outputs.

Procedure

0. Detect the stack

Infer the IaC flavour from the repo before generating anything:

find . -maxdepth 3 -name '*.tf' 2>/dev/null | head           # Terraform
find . -maxdepth 3 -name '*.bicep' 2>/dev/null | head        # Bicep
find . -maxdepth 3 -name 'Pulumi.yaml' 2>/dev/null | head    # Pulumi
find . -maxdepth 3 -name 'cdk.json' 2>/dev/null | head       # AWS CDK
find . -maxdepth 3 -name 'template.yaml' 2>/dev/null | head  # CloudFormation / SAM
ls ansible/ playbooks/ 2>/dev/null                           # Ansible
cat .terraform-version .tool-versions 2>/dev/null            # pinned TF / asdf

Also check whether the user expressed a preference in their request (e.g. "generate Terraform" vs "generate Bicep"). Declared preference overrides detection.

This skill supports terraform, bicep+azure, and pulumi. If detection shows AWS CDK, CloudFormation / SAM, Ansible, Crossplane, Chef/Puppet, or Cloud-provider consoles as the source of truth, STOP and report. Dropping a Terraform module into a CDK repo (or vice versa) creates drift between two state stores and is the single biggest IaC regret teams have.

If no IaC tool is detected and the user hasn't specified one, ask which of the three supported stacks they want. Do not guess.

1. Pick the layout

infrastructure/
  terraform/
    modules/
      eks-cluster/
      rds-postgres/
      s3-bucket/
      vpc/
      iam-role/
    envs/
      dev/
      staging/
      prod/

Each env has its own backend.tf pointing at a different state key. Modules are versionless in-repo; publish to a registry once stable.

2. Configure remote state with locking

Terraform + S3/DynamoDB:

terraform {
  required_version = ">= 1.7"
  backend "s3" {
    bucket         = "acme-tfstate-prod"
    key            = "checkout/prod/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "acme-tfstate-locks"
    encrypt        = true
    kms_key_id     = "alias/tfstate"
  }
}

Bicep + Azure Storage:

Azure uses deployment stacks, not state files, but ARM-template outputs persist. Configure a storage account for artifact/what-if output:

az deployment sub create \
  --name checkout-prod-$(date +%s) \
  --location eastus \
  --template-file main.bicep \
  --parameters @prod.bicepparam

Pulumi + Azure Blob backend:

pulumi login azblob://acme-pulumi-state?storage_account=acmepulumistate

3. Generate the resource (examples)

VPC (Terraform, AWS)
module "vpc" {
  source             = "../../modules/vpc"
  name               = "${var.name_prefix}-vpc"
  cidr               = "10.40.0.0/16"
  azs                = ["us-east-1a", "us-east-1b", "us-east-1c"]
  public_subnets     = ["10.40.0.0/20", "10.40.16.0/20", "10.40.32.0/20"]
  private_subnets    = ["10.40.64.0/20", "10.40.80.0/20", "10.40.96.0/20"]
  enable_nat_gateway = true
  single_nat_gateway = var.env != "prod"
  enable_flow_log    = true
  flow_log_destination_type = "cloud-watch-logs"
  tags               = local.tags
}
EKS cluster (Terraform)
module "eks" {
  source  = "terraform-aws-modules/eks/aws"
  version = "~> 20.24"

  cluster_name                    = "${var.name_prefix}-${var.env}"
  cluster_version                 = "1.30"
  cluster_endpoint_public_access  = false
  cluster_endpoint_private_access = true

  enable_irsa                  = true
  cluster_encryption_config    = [{ resources = ["secrets"] }]
  cluster_enabled_log_types    = ["api", "audit", "authenticator", "controllerManager", "scheduler"]

  vpc_id     = module.vpc.vpc_id
  subnet_ids = module.vpc.private_subnets

  eks_managed_node_groups = {
    default = {
      min_size       = var.env == "prod" ? 3 : 1
      max_size       = var.env == "prod" ? 10 : 4
      desired_size   = var.env == "prod" ? 3 : 2
      instance_types = ["m6i.large"]
      capacity_type  = var.env == "prod" ? "ON_DEMAND" : "SPOT"
      labels         = { workload = "general" }
    }
  }

  tags = local.tags
}
RDS Postgres
module "db" {
  source  = "terraform-aws-modules/rds/aws"
  version = "~> 6.10"

  identifier                          = "${var.name_prefix}-${var.env}"
  engine                              = "postgres"
  engine_version                      = "16.4"
  instance_class                      = var.env == "prod" ? "db.r6g.xlarge" : "db.t4g.medium"
  allocated_storage                   = var.env == "prod" ? 200 : 50
  storage_encrypted                   = true
  kms_key_id                          = aws_kms_key.rds.arn
  multi_az                            = var.env == "prod"
  deletion_protection                 = var.env == "prod"
  iam_database_authentication_enabled = true
  publicly_accessible                 = false
  backup_retention_period             = var.env == "prod" ? 30 : 7
  performance_insights_enabled        = true

  db_subnet_group_name   = module.vpc.database_subnet_group_name
  vpc_security_group_ids = [aws_security_group.rds.id]

  manage_master_user_password = true
  master_user_secret_kms_key_id = aws_kms_key.rds.arn

  tags = local.tags
}

Never put a raw password in code; the manage_master_user_password flag stores the generated password in Secrets Manager.

S3 bucket with versioning + encryption
resource "aws_s3_bucket" "artifacts" {
  bucket = "${var.name_prefix}-artifacts-${var.env}"
  tags   = local.tags
}

resource "aws_s3_bucket_public_access_block" "artifacts" {
  bucket                  = aws_s3_bucket.artifacts.id
  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

resource "aws_s3_bucket_versioning" "artifacts" {
  bucket = aws_s3_bucket.artifacts.id
  versioning_configuration { status = "Enabled" }
}

resource "aws_s3_bucket_server_side_encryption_configuration" "artifacts" {
  bucket = aws_s3_bucket.artifacts.id
  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm     = "aws:kms"
      kms_master_key_id = aws_kms_key.s3.arn
    }
    bucket_key_enabled = true
  }
}

resource "aws_s3_bucket_lifecycle_configuration" "artifacts" {
  bucket = aws_s3_bucket.artifacts.id
  rule {
    id     = "expire-old-versions"
    status = "Enabled"
    noncurrent_version_expiration { noncurrent_days = 90 }
    abort_incomplete_multipart_upload { days_after_initiation = 7 }
  }
}
IAM role (least privilege)
data "aws_iam_policy_document" "assume" {
  statement {
    effect = "Allow"
    actions = ["sts:AssumeRoleWithWebIdentity"]
    principals {
      type        = "Federated"
      identifiers = [module.eks.oidc_provider_arn]
    }
    condition {
      test     = "StringEquals"
      variable = "${module.eks.oidc_provider}:sub"
      values   = ["system:serviceaccount:checkout:checkout-api"]
    }
  }
}

data "aws_iam_policy_document" "checkout_api" {
  statement {
    effect = "Allow"
    actions = ["s3:GetObject", "s3:PutObject"]
    resources = ["${aws_s3_bucket.artifacts.arn}/checkout/*"]
  }
  statement {
    effect = "Allow"
    actions = ["secretsmanager:GetSecretValue"]
    resources = [aws_secretsmanager_secret.db.arn]
  }
}

resource "aws_iam_role" "checkout_api" {
  name               = "${var.name_prefix}-checkout-api-${var.env}"
  assume_role_policy = data.aws_iam_policy_document.assume.json
  tags               = local.tags
}

resource "aws_iam_role_policy" "checkout_api" {
  role   = aws_iam_role.checkout_api.id
  policy = data.aws_iam_policy_document.checkout_api.json
}

No Action: *, no Resource: *. Scope actions to minimum set, resources to specific ARNs.

Bicep: AKS (private cluster)
param location string = resourceGroup().location
param namePrefix string
param env string
var tags = { Env: env, Owner: 'platform', ManagedBy: 'bicep' }

resource aks 'Microsoft.ContainerService/managedClusters@2024-09-01' = {
  name: '${namePrefix}-${env}'
  location: location
  identity: { type: 'SystemAssigned' }
  properties: {
    dnsPrefix: '${namePrefix}-${env}'
    kubernetesVersion: '1.30'
    networkProfile: { networkPlugin: 'azure', networkPolicy: 'cilium', loadBalancerSku: 'standard' }
    apiServerAccessProfile: { enablePrivateCluster: true, authorizedIPRanges: [] }
    agentPoolProfiles: [ {
      name: 'system', mode: 'System'
      count: env == 'prod' ? 3 : 1
      vmSize: 'Standard_D4s_v5'
      availabilityZones: ['1', '2', '3']
    } ]
    addonProfiles: {
      azureKeyvaultSecretsProvider: { enabled: true, config: { enableSecretRotation: 'true' } }
    }
  }
  tags: tags
}
Pulumi (Python) — S3 bucket
import pulumi, pulumi_aws as aws

name_prefix = pulumi.Config().require("namePrefix")
tags = {"Env": pulumi.get_stack(), "Owner": "platform", "ManagedBy": "pulumi"}

bucket = aws.s3.BucketV2(f"{name_prefix}-artifacts", tags=tags)
aws.s3.BucketVersioningV2("ver", bucket=bucket.id,
    versioning_configuration={"status": "Enabled"})
aws.s3.BucketServerSideEncryptionConfigurationV2("sse", bucket=bucket.id, rules=[{
    "apply_server_side_encryption_by_default": {"sse_algorithm": "aws:kms"},
    "bucket_key_enabled": True}])
aws.s3.BucketPublicAccessBlock("pab", bucket=bucket.id,
    block_public_acls=True, block_public_policy=True,
    ignore_public_acls=True, restrict_public_buckets=True)

4. Validate

terraform fmt -recursive
terraform init -backend=false
terraform validate
tflint --recursive
checkov -d . --framework terraform
terraform plan -out plan.bin

For Bicep:

bicep build main.bicep
az deployment sub what-if --location eastus --template-file main.bicep --parameters @prod.bicepparam
Invoke-PSRule -Module PSRule.Rules.Azure -InputPath .

5. CI integration

  • On MR: run fmt, validate, tflint, checkov, plan. Post the plan as an MR comment.
  • On merge to main: run apply in the target env workspace, gated by an environment approver.
  • Store plan artifacts with 30-day retention for audit.

Refer to references/iac-best-practices.md for module structure, naming, and policy-as-code details.

Examples

Example 1 — Net-new EKS stack for checkout-api dev

Inputs: tool=terraform, cloud=aws, resources=[vpc, eks, rds-postgres, s3, iam-role-least-privilege], env=dev, region=us-east-1, name_prefix=acme-checkout.

Generates infrastructure/terraform/envs/dev/ with a VPC (single NAT), a single-AZ t4g RDS, a 2-node SPOT EKS group, one S3 bucket, and an IRSA role for the app. Remote state in s3://acme-tfstate-dev with DynamoDB locking.

Example 2 — Azure Postgres Flexible Server in prod

Inputs: tool=bicep, cloud=azure, resources=[azure-postgres-flexible], env=prod, region=eastus, name_prefix=acme-ledger.

Generates infrastructure/bicep/envs/prod/postgres.bicep with zone-redundant HA, 30-day backup retention, geo-redundant backups to westus, private endpoint in an existing VNet, and AAD authentication enabled. Password is generated via @secure() parameter and pulled from Key Vault at deploy time.

Constraints

  • Do not produce output for a stack outside supported-stacks. If detection shows AWS CDK, CloudFormation/SAM, Ansible, Crossplane, Chef/Puppet, or console-as-source-of-truth, STOP and report. Generating a parallel Terraform module against an existing CDK codebase creates two state stores that will drift and cannot be safely reconciled.
  • Never hard-code credentials. Use manage_master_user_password, Key Vault references, or Secrets Manager.
  • Never open a security group/NSG to 0.0.0.0/0 on administrative ports. SSH/RDP require bastion or SSM.
  • Never use * in IAM actions or resources for application roles.
  • Never disable deletion protection in prod modules.
  • Never commit plaintext .tfvars with real values for prod. Use -var-file pulled from a secret store at CI time.
  • Modules must be region-agnostic; parametrize every AZ/region.
  • Every resource must carry the mandatory tag set.

Quality checks

  • terraform fmt -check -recursive passes.
  • terraform validate passes.
  • tflint --recursive has zero issues.
  • checkov -d . passes with no HIGH or CRITICAL findings, and any suppressions are annotated with justification.
  • terraform plan shows only the intended changes; no incidental diffs.
  • Remote state backend is configured; terraform init succeeds without local state fallback.
  • All outputs are documented in README.md (use terraform-docs).
  • For prod: deletion protection, multi-AZ, encryption-at-rest, and backups are all true.
  • No secrets in plan output; masked via sensitive = true where appropriate.

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.