Adam Divall

Walkthrough Guides and Other Useful Information on AWS

From Analysis to Remediation in Minutes: Using AWS Transform and Kiro to Tackle IaC Technical Debt

2026-04-28 8 min read Mofrnisation Adam Divall

Infrastructure-as-Code repositories have a habit of quietly accumulating technical debt. A Lambda runtime drifts toward end-of-life, a copy-pasted resource block introduces a subtle bug, IAM policies stay broader than they need to be. These issues rarely surface until something breaks in production — or until an auditor asks uncomfortable questions.

In this post, I walk through how I used AWS Transform (ATX) inside Kiro to perform a comprehensive analysis of a real CloudFormation project, surface seven technical debt findings, and remediate six of them — all without leaving the IDE.

The Target: A Multi-Account Networking IaC Project

The project is a set of CloudFormation templates designed for Customizations for Control Tower (CfCT). It automates centralized IP address management across a multi-account AWS Organization using Amazon VPC IPAM. The architecture follows a common enterprise pattern — three templates deployed to different account tiers:

  • A delegation template — Deployed to the Management Account. Uses a Lambda-backed Custom Resource to delegate IPAM administration to a shared services account.
  • A pool configuration template — Deployed to the shared services account. Creates the IPAM instance, a custom scope, and a hierarchical pool structure (Top → Regional → Environment), then shares environment pools across the Organization via AWS RAM.
  • A VPC provisioning template — Deployed to member accounts. Looks up the correct IPAM pool by region and environment tag, provisions a VPC with an IPAM-allocated CIDR, 9 subnets across 3 tiers and 3 AZs, an Internet Gateway, per-AZ NAT Gateways, and full routing.

It’s a small codebase — roughly 925 lines across 3 templates, 2 JSON parameter files, a standalone Python Lambda file, and a readme. Small enough to review manually, but that’s exactly the kind of project where issues hide in plain sight.

Setting Up the AWS Transform Power in Kiro

AWS Transform is available as a Kiro Power — a packaged capability that brings documentation, workflow guides, and tooling directly into the IDE. After installing it from the Powers panel, activation is a single step in chat.

The power requires three prerequisites, all verified automatically:

  1. AWS CLI — installed and authenticated with a valid session
  2. ATX CLI — the AWS Transform command-line tool (installed via curl -fsSL https://transform-cli.awsstatic.com/install.sh | bash)
  3. IAM permissions — the AWSTransformCustomFullAccess managed policy attached to your identity

With those in place, the power discovers available Transformation Definitions (TDs) — reusable transformation recipes published to your AWS account. ATX ships with several built-in TDs covering Java, Python, and Node.js version upgrades, AWS SDK migrations, and codebase analysis.

Step 1: Comprehensive Codebase Analysis

I pointed ATX at the repository and asked for a comprehensive analysis. ATX matched the repository to the AWS/comprehensive-codebase-analysis TD — a deep static analysis that generates hierarchical, cross-referenced documentation covering architecture, behavior, security, and technical debt.

The transformation ran locally, executing a 9-step plan:

  1. Create documentation structure — scaffold the output directory hierarchy
  2. Full static analysis — read every source file, identify languages, frameworks, and patterns
  3. Technical debt report — surface findings with severity ratings and an AWS transformation recommendation
  4. Architecture documentation — system overview, component breakdown, dependency mapping, design patterns
  5. Behavior documentation — business logic, workflows, decision trees, error handling
  6. Analysis documentation — code metrics, cyclomatic complexity, dependency graphs, security patterns
  7. Diagrams and migration planning — text-based architecture diagrams, deployment ordering, test specifications
  8. Root-level navigation — master README with cross-references across all generated documents
  9. Validation — verify all files exist, contain substantive content, and pass exit criteria

The entire analysis completed in under 20 minutes and produced 32 documentation files — a complete knowledge base for a project that previously had a single readme.

What Kiro Brings to the Workflow

Throughout the transformation, Kiro provided real-time visibility. The ATX process ran in the background while Kiro:

  • Extracted the conversation ID and reported it immediately
  • Polled the conversation log every 60 seconds and relayed progress updates
  • Opened artifacts (like the transformation plan) in the editor as they appeared
  • Surfaced the Source Control panel prompt so I could watch file-level diffs as ATX committed after each step

This is the difference between running a CLI tool in a terminal and having an agentic workflow integrated into your development environment. The agent doesn’t just execute — it monitors, reports, and keeps you informed.

Step 2: The Findings

ATX identified 7 technical debt items across 3 severity levels:

High Severity

1. Python 3.9 Lambda Runtime — Approaching EOL

Both Lambda functions used Runtime: python3.9. Python 3.9 reached end-of-life in October 2025, meaning AWS Lambda would eventually stop supporting new deployments and updates. The code only uses boto3, cfnresponse, and standard library modules — no compatibility risk with newer runtimes.

Medium Severity

2. Resource Share References Non-Existent Resources

This was the most interesting find. The AWS RAM ResourceShare included ARN references to resources for a third region — but those resources were never defined in the template. Only Region 1 and Region 2 pool resources existed. This would cause a CloudFormation deployment failure with an unresolved reference error.

This is the kind of bug that static analysis catches but manual review often misses — especially in a template with repetitive resource blocks where your eyes glaze over the pattern.

3. Duplicate Lambda Code

A standalone Python file in the lambda/ directory was an exact duplicate of the inline ZipFile code in one of the CloudFormation templates. Since CfCT deploys the inline version, the standalone file was dead code — a maintenance burden waiting to cause drift.

4. Inconsistent Parameter AllowedValues

Two of the three templates allowed Production, UAT, and Development for the environment tag parameter. But the VPC provisioning template only allowed Production and Development — silently preventing UAT VPC provisioning even though UAT IPAM pools existed upstream.

Low Severity

5. Overly Broad IAM Permissionsiam:CreateServiceLinkedRole bundled with EC2/Organizations actions under Resource: "*" instead of scoped to the specific service-linked role ARN.

6. Hardcoded 2-Region Architecture — The pools template used !Select [0, ...] and !Select [1, ...] with no mechanism for dynamic region expansion.

7. No CloudWatch Logs Encryption — Log Groups created without KMS encryption.

Step 3: Remediation

With the findings documented, I asked Kiro to remediate them directly. Six of the seven were addressed:

Runtime Upgrade (Finding 1)

# Before
Runtime: python3.9

# After
Runtime: python3.12

Applied to both templates containing Lambda functions.

Resource Share Bug Fix (Finding 2)

Removed the invalid references to non-existent Region 3 resources from the RAM ResourceShare:

# Removed — these resources were never defined
- !GetAtt rPoolRegion3Prod.Arn
- !GetAtt rPoolRegion3UAT.Arn
- !GetAtt rPoolRegion3Dev.Arn

Dead Code Removal (Finding 3)

Deleted the standalone Lambda file entirely. The inline ZipFile in the CloudFormation template is the source of truth for CfCT deployments.

Parameter Alignment (Finding 4)

Added the missing UAT value to the environment parameter’s AllowedValues in the VPC provisioning template:

# Before
AllowedValues:
  - Production
  - Development

# After
AllowedValues:
  - Production
  - UAT
  - Development

IAM Scoping (Finding 5)

Split iam:CreateServiceLinkedRole into its own IAM policy statement with a scoped resource and service condition:

- Effect: "Allow"
  Action:
    - "iam:CreateServiceLinkedRole"
  Resource: "arn:aws:iam::*:role/aws-service-role/ipam.amazonaws.com/AWSServiceRoleForIPAM*"
  Condition:
    StringLike:
      "iam:AWSServiceName": "ipam.amazonaws.com"

KMS Encryption (Finding 7)

Added a KMS key with automatic rotation and a CloudWatch Logs service permission policy to each template, then referenced it from the Log Group:

rLogGroupKmsKey:
  Type: AWS::KMS::Key
  Properties:
    Description: "KMS key for encrypting Lambda CloudWatch Log Group"
    EnableKeyRotation: true
    KeyPolicy:
      # ... root account access + CloudWatch Logs service permissions

rLambdaLogGroup:
  Type: AWS::Logs::LogGroup
  Properties:
    LogGroupName: !Sub /aws/lambda/${rLambdaFunction}
    RetentionInDays: !Ref pLogRetention
    KmsKeyId: !GetAtt rLogGroupKmsKey.Arn

What Was Skipped

Finding 6 (Hardcoded 2-Region Architecture) was intentionally skipped. Converting the template from hardcoded !Select indices to a dynamic region model is an architectural redesign — not a simple remediation. It would require either CloudFormation macros, nested stacks with a loop construct, or a move to CDK/Terraform. That’s a separate workstream.

Step 4: Validation, Commit, and Merge

After all changes were applied, cfn-lint validated the templates with no new errors. Kiro then:

  1. Created a feature branch
  2. Made two clean commits — one for the 32 documentation files, one for the 6 remediations
  3. Pushed the branch and created a GitHub PR with a structured description
  4. Merged the PR and cleaned up the remote branch

The entire flow — from “analyse this repo” to “merged PR” — happened in a single Kiro session.

Key Takeaways

ATX finds what humans skip. The phantom Region 3 resource share bug is a perfect example. In a template with repetitive resource blocks, it’s easy to copy-paste a section for a future region and forget to create the backing resources. Static analysis doesn’t get fatigued by repetition.

Small codebases aren’t immune. This project is under 1,000 lines. It still had 7 findings, including a deployment blocker. Technical debt scales with time, not lines of code.

The agentic workflow matters. Running cfn-lint in a terminal catches syntax errors. Running ATX through Kiro catches architectural issues, generates documentation, and remediates findings — all in a continuous flow where the agent monitors progress, opens artifacts, and keeps you informed without context-switching.

AWS Transform custom goes beyond language upgrades. The comprehensive codebase analysis TD is particularly useful for IaC projects that lack documentation. In 20 minutes, it produced a 32-file documentation suite that would take days to write manually — covering architecture, behavior, security patterns, migration planning, and technical debt with cross-references throughout.

If you’re managing CloudFormation, CDK, or Terraform repositories at scale, the combination of AWS Transform and Kiro gives you a practical path from “we should probably review that” to “it’s analysed, documented, remediated, and merged.”