Building blocks you will touch
Before this: Why manual onboarding breaks settled why multi-team hand migration drifts.
This page is orientation only — no install steps. Glossary tooltips cover one-line definitions; here is how the pieces fit this factory story. If you already live in these tools, skim and move on to Install the toolchain. Commands and trees live in jajera/kiro-eks-argocd-migration.
The path you already have
Section titled “The path you already have”Amazon EKS
Amazon Elastic Kubernetes Service — the managed Kubernetes control plane this factory targets. is the managed Kubernetes control plane. This factory assumes a cluster already exists. Labs A–C do not create EKS; they shape app trees and prove policy offline so you are not inventing layout on a live API.
Argo CD
Section titled “Argo CD”Argo CD
GitOps continuous delivery controller that syncs Kubernetes manifests from Git into the cluster. is the GitOps sync engine. Humans merge a PR; Argo syncs what landed in Git. The factory drafts manifests and Application wiring — it does not bypass review, and it does not kubectl apply from chat.
Together: EKS runs workloads; Argo CD reconciles desired state from Git. The factory makes the Git side consistent so both stay predictable at scale.
Policy offline before the cluster
Section titled “Policy offline before the cluster”Gatekeeper
Section titled “Gatekeeper”OPA Gatekeeper
OPA Gatekeeper — Kubernetes admission controller that evaluates ConstraintTemplates against cluster objects. is the in-cluster admission controller. Once installed, it evaluates ConstraintTemplates
Gatekeeper CRD that defines a Rego policy and the shape of parameters a Constraint can set. against objects as they enter the API. Live Lab D (out of scope here) is where that webhook matters on a real cluster.
gator
Gatekeeper offline CLI — runs `gator verify` against constraint suites without a live cluster (Lab A). is the offline Gatekeeper CLI. Lab A runs gator verify against constraint suites on your laptop — no cluster credentials, no webhook. That is why setup pins a gator version and why chart skew is called out separately: the CLI and the vendored Helm chart are related but not the same binary pin.
Rule of thumb: Gatekeeper enforces on the cluster; gator proves the same rules before the
cluster is in the loop. Which violations actually fail depends on each Constraint’s
enforcementAction — see below.
The constraint set
Section titled “The constraint set”Every rule below is a ConstraintTemplate under infrastructure/gatekeeper/constraint-templates/, each bound to a scope by a matching Constraint
Gatekeeper object that binds a ConstraintTemplate to a match scope (kinds, namespaces, labels)., each proven by a gator suite. Lab A walks the full chain for one of these (httpsonly); the rest follow the same pattern.
| Constraint | What it checks |
|---|---|
httpsonly |
Ingress Kubernetes API object that exposes HTTP/HTTPS routes into the cluster — often an ALB Ingress on EKS. without kubernetes.io/ingress.allow-http: "false" — no plaintext HTTP ingress |
k8singresswafv2 |
Internet-facing ALB AWS Application Load Balancer — common ingress target once an app is live on the cluster. Ingress missing a valid regional WAFv2 AWS WAFv2 — current WAF API; `k8singresswafv2` requires a valid regional Web ACL ARN on public Ingress. Web ACL WAFv2 Web ACL — the filter set attached to an ALB; internet-facing Ingress must reference a regional ARN. ARN |
requiredlabels |
Resources missing required labels or with label values that fail the pattern |
disallowedtags |
Container images pinned to a blocked tag (for example latest) |
containerlimits |
Containers without memory/CPU limits, or limits above the allowed ceiling |
privileged-containers |
Pods running with privileged: true Pod/container security context with `privileged: true` — nearly full host capabilities; blocked by Gatekeeper here. |
allow-privilege-escalation |
Containers with allowPrivilegeEscalation: true Container securityContext flag; when true a process can gain more privileges than its parent — blocked here. |
host-namespaces |
Pods sharing the host PID or IPC namespace Sharing the host PID or IPC namespace with a pod — blocked so workloads cannot see or signal host processes. |
host-filesystem |
Pods mounting host paths Mounting hostPath volumes into a pod — blocked except where an allow-list explicitly permits a path. outside the allowed list |
block-nodeport-services |
Any Service of type NodePortService type that opens a port on every node — blocked here so traffic enters via Ingress/ALB instead of node ports. |
disallow-default-namespace |
Namespaced resources deployed into default |
disallowanonymous |
RBAC Kubernetes Role-Based Access Control — Roles, ClusterRoles, and bindings that grant API permissions. bindings that grant system:anonymous or system:unauthenticated |
networkpolicy-egress-defined |
Namespaces missing a NetworkPolicy Kubernetes NetworkPolicy — namespace-scoped rules for pod ingress/egress; this set requires egress to be defined. that defines egress |
verifydeprecatedapi |
Objects using a deprecated Kubernetes API version A Kubernetes API version the cluster version has already deprecated — `verifydeprecatedapi` rejects those objects. for the cluster’s version |
Defined is not the same as enforced
Section titled “Defined is not the same as enforced”The table above is an inventory of Rego checks. Whether a violation actually fails is spec.enforcementAction on each Constraint
Gatekeeper object that binds a ConstraintTemplate to a match scope (kinds, namespaces, labels).:
apiVersion: constraints.gatekeeper.sh/v1beta1kind: K8sHttpsOnlymetadata: name: ingress-https-onlyspec: enforcementAction: deny # dryrun | deny match: kinds: - apiGroups: ["extensions", "networking.k8s.io"] kinds: ["Ingress"]Under dryrun, Gatekeeper still evaluates the object and can record a violation — but it does
not reject admission, and app checks that run gator test --deny-only stay green. Nothing in
the PR path fails, so non-compliant manifests keep shipping. The bite comes later: the day you
flip the same field to deny, every accumulated violation starts blocking at once.
This factory follows that stance for ready rules (including httpsonly): they ship as deny. The rare holdout is rules that need real account-specific values you do not have yet — notably WAFv2
AWS WAFv2 — current WAF API; `k8singresswafv2` requires a valid regional Web ACL ARN on public Ingress. Web ACL ARNs — which stay dryrun until those ARNs exist. Lab A walks one Constraint end to end, including this field.
How Kiro reaches context
Section titled “How Kiro reaches context”MCP
Model Context Protocol adapters — docs MCP stays on; live cluster adapters stay off until a human intentionally enables them. (Model Context Protocol) is how Kiro
Amazon's agentic IDE — runs vibe or spec sessions against the factory's `.kiro/` steering, skills, and hooks. attaches tools and doc sources to a session. In this factory:
- Docs MCP stays on so the agent can read project guidance without inventing APIs.
- Live cluster adapters stay off until a human intentionally enables them — the Git-only hook story in Lab C depends on that boundary.
MCP is not something you install in setup for Labs A–C beyond what Kiro already ships. You will see the config map in Lab B; you do not need a custom MCP server to start Lab A.
What you install next
Section titled “What you install next”Setup only gets you a clone of the upstream factory repo, gator, kustomize, and Kiro. Concepts above are the map; install is the checklist.
Next: Install the toolchain — clone, pin gator, and confirm Lab prerequisites.