Å sette opp et nytt prosjekt i AWS kan være tidkrevende. Du må opprette nye AWS-kontoer, konfigurere riktige tilganger, sette opp GitHub-repositories, og koble alt sammen. Hva om hele denne prosessen kunne automatiseres med én enkelt kodeendring?
I dette blogginnlegget viser jeg hvordan jeg har bygget et system som automatisk provisionerer komplette prosjektmiljøer – fra AWS-kontoer til ferdigkonfigurerte GitHub-repositories – ved å kun spesifisere et prosjektnavn i en konfigurasjonsfil.

Jeg antar litt bakgrunnkunnskap om Terraform og AWS. For en introduksjon kan du lese mitt tidligere blogginnlegg om temaet.
Problemet
Når man skal starte et nytt prosjekt i AWS med moderne best practices er det mye som må eller bør settes opp:
- Separate AWS-kontoer for hvert miljø (dev, stage, prod) - gir isolasjon og sikkerhet
- Organisasjonsstruktur i AWS Organizations - for å strukturere kontoer
- IAM-roller og tilganger for å deploye fra GitHub Actions
- S3-bøtter for OpenTofu/Terraform state
- GitHub-repositories for kode og infrastruktur
- OpenID Connect (OIDC) setup for sikker autentisering uten lagrede secrets
- GitHub Actions variabler som kobler alt sammen
Man kan gjøre det enklere ved å bruke én AWS-konto, hardkodede credentials, og manuell konfigurasjon. Men det gir dårligere isolasjon, mer kompleks IAM-håndtering, og økt risiko.
Problemet er at å gjøre dette riktig er mye manuelt arbeid som må gjentas for hvert prosjekt. Og det blir fort uoversiktlig når man har mange prosjekter.
Ønsket resultat
Målet var en løsning som gir følgende for hvert nytt prosjekt:
- Egne AWS-kontoer for hvert miljø - Full isolasjon mellom dev, stage og prod. Dette gir bedre sikkerhet (begrenset blast radius ved feil), enklere kostnadsoppfølging per miljø, og ingen risiko for at ressurser i dev påvirker prod.
- Dedikert IaC-repo - Ett Terraform-repo per prosjekt. Dette holder infrastrukturkoden organisert og lar hvert team eie sin egen infrastruktur.
- Code repositories - Separate repos for frontend, backend, eller andre komponenter etter behov. Gir fleksibilitet i struktur og deployment-pipelines.
- Minimal manuell innsats - Hele oppsettet skal kunne gjøres ved å legge til noen linjer i én konfigurasjonsfil.
Målet er altså å gå fra "null" til "produksjonsklar infrastruktur" på noen få minutter!
Løsningen: IaC for IaC
Løsningen er basert på OpenTofu (en open source fork av Terraform) som automatiserer hele prosessen. OpenTofu har en viktig fordel over Terraform: det støtter dynamisk for_each
på providers, noe som gjør det mulig å assume inn i flere AWS-roller på en elegant måte.
Slik fungerer det
Hele prosessen starter med én enkel fil: config/projects.tfvars
. Her definerer du prosjektene dine:
That's it! Fra denne konfigurasjonen vil systemet automatisk:
- Opprette AWS-kontoer for hvert miljø
- Sette opp GitHub-repositories (både kode-repos og IaC-repo)
- Bootstrappe hver konto med nødvendig infrastruktur
- Koble alt sammen: It just works!
Arkitekturen
Løsningen består av tre hovedsteg som kjører sekvensielt i GitHub Actions:
Steg 1: Main Environment - Opprette AWS-kontoer og repos
Dette oppretter:
- En dedikert Organizational Unit (OU) for prosjektet
- Separate AWS-kontoer for hvert miljø (dev, stage, prod osv.)
- GitHub-repositories for kode
Steg 2: Bootstrap - Sette opp infrastruktur i hver konto
Her kommer den smarte delen, og grunnen til at vi bruker OpenTofu. Systemet bruker OpenTofu sin for_each
på providers for å dynamisk "assume_role" inn i hver nyopprettede konto (les mer om dynamiske providers her):
Bootstrap-modulen setter opp:
GitHub OIDC Provider for sikker autentisering uten secrets:
IAM-rolle som GitHub Actions kan bruke:
S3 bucket for state file til den nye IaC-koden:
Steg 3: Project IaC Repos - Opprette IaC-repositories
Til slutt opprettes et IaC-repository basert på en template, med miljøvariabler som kobler dem til AWS:
Dette oppretter et GitHub-repo basert på en template, med miljøer (dev, stage, prod) og miljøvariabler som peker til riktige IAM-roller i AWS.
Hvorfor 3 steg? 🤔
Rekkefølgen er ikke tilfeldig. Først må vi opprette selve kontoene og reposene som resten av prosessen skal bruke. Deretter kan vi bootstrappe hver konto med nødvendige roller, OIDC-oppsett og state-bøtter slik at de faktisk kan administreres videre. Til slutt, når alt det grunnleggende er på plass, genereres prosjektets IaC-repo som tar over ansvaret for den videre infrastrukturen. Med andre ord – hvert steg bygger på resultatet fra det forrige, og derfor må de kjøres sekvensielt.
Men Terraform fikser jo avhengigheter, gjør det ikke?
Som regel, ja – Terraform håndterer rekkefølgen mellom ressurser så lenge alt skjer innenfor samme konto og provider. Her er det annerledes: vi oppretter helt nye AWS-kontoer, og de eksisterer ikke før første apply
er ferdig. Først da får vi tilgang til dem og kan anta roller for å kjøre neste steg. Det betyr at Terraform rett og slett ikke kan planlegge alt i én omgang, fordi providerne og tilganger til de nye kontoene ikke finnes ennå. Når infrastrukturen krysser konto- og autentiseringsgrenser, må vi dele opp prosessen i flere omganger for at alt skal henge sammen.
Workflowen i praksis
Hele prosessen er automatisert gjennom GitHub Actions med innebygd godkjenning:
- Utvikler legger til et nytt prosjekt i
config/projects.tfvars
- Pull Request opprettes - workflow kjører
tofu plan
og kommenterer planen på PR-en - Review og merge til main branch
- Automatisk apply starter, men venter på manuell godkjenning
- Godkjenner får en GitHub issue og må godkjenne endringene
- Tre separate jobs kjører sekvensielt:
tofu-apply-main
: Oppretter AWS-kontoer og code repostofu-apply-bootstrap
: Setter opp OIDC, roller og S3-bøttertofu-apply-project-iac-repo
: Oppretter IaC-repo med riktige variabler
Hver job krever manuell godkjenning via GitHub Issues før den kjører.
Hvorfor OpenTofu fremfor Terraform?
Et kritisk aspekt av denne løsningen er muligheten til å dynamisk "assume" roller inn i flere AWS-kontoer. Dette krever for_each
på provider-nivå:
Terraform støtter ikke dette, men OpenTofu gjør det. Dette gjør det mulig å bootstrappe et vilkårlig antall AWS-kontoer i samme OpenTofu-kjøring.
Sikkerhet
Løsningen bygger på flere sikkerhetsprinsipper:
OIDC fremfor long-lived credentials: GitHub Actions autentiserer seg mot AWS via OpenID Connect, ingen hemmeligheter lagres
Minste privilegium: Hver IAM-rolle er scopet til ett spesifikt GitHub-repository
Manuell godkjenning: Alle endringer må godkjennes manuelt før apply
Om AdministratorAccess-rollen
Et viktig designvalg er at IaC-repoene får AdministratorAccess
i sine respektive AWS-kontoer. Dette er en bevisst avveining mellom sikkerhet og brukbarhet.
Hvorfor AdministratorAccess er akseptabelt:
IaC-roller trenger bred tilgang - Et IaC-repo kan potensielt trenge å opprette hvilke som helst AWS-ressurser (VPCs, RDS, ECS, IAM-roller, Lambda, osv.). Å forutsi nøyaktig hvilke permissions som trengs er vanskelig og vedlikeholdskrevende.
Kontoen er isolert - Hvert prosjekt får egne AWS-kontoer. En kompromittert IaC-rolle påvirker kun det prosjektets ressurser, ikke hele AWS-organisasjonen.
OIDC begrenser angrepsflatene - Rollen kan kun assumes fra ett spesifikt GitHub-repository. Det er ikke en generell admin-credential som kan brukes fra hvor som helst.
Den virkelige sikkerhetsgrensen er GitHub - Tilgang til å endre infrastruktur styres gjennom:
- GitHub repository permissions (hvem kan committe)
- Branch protection rules (krever PR-godkjenninger)
- Code review fra teammedlemmer
- GitHub Actions approval gates for prod-miljøer
Infrastruktur som kode krever tillit - Personer som skriver infrastrukturkode må uansett ha tillit til å gjøre endringer i produksjon. Det er vanskelig å ha "begrenset IaC".
Alternative tilnærminger:
Hvis du ønsker strengere kontroll, kan du:
- Service Control Policies (SCPs) på organisasjonsnivå som blokkerer farlige operasjoner (f.eks. slette CloudTrail logs, disable GuardDuty)
- Custom IAM policies per prosjekt hvis du vet at prosjektet kun trenger spesifikke tjenester
- GitHub Environment reviewers som krever manuell godkjenning før prod-deployments
- AWS CloudTrail for å logge alt som gjøres med rollen
Filosofien:
Løsningen bygger på en "high trust"-modell hvor folk som har tilgang til IaC-repoer er betrodde med bred AWS-tilgang. Den reelle sikkerheten ligger i:
- Hvem får commit-tilgang til IaC-repos
- Code review og godkjenningsprosesser
- Audit logging og overvåking av hva som faktisk gjøres
Denne tilnærmingen balanserer sikkerhet med brukbarhet, og unngår kompleksitet som i praksis gir falsk trygghet uten reell sikkerhetsgevinst.
Sletting av prosjekter
Når et prosjekt skal nedlegges, er det noen manuelle steg som må gjøres på grunn av AWS sine restriksjoner:
- Fjern prosjektet fra
config/projects.tfvars
- Flytt AWS-kontoene til root OU i AWS Organizations Console
- Lukk kontoene manuelt i AWS Console
- Re-run feila GitHub Actions job som vil fjerne OU-en
- Fjern IaC-repoet (manuelt eller via OpenTofu)
Dette er nødvendig fordi AWS krever manuell godkjenning for å lukke kontoer.
Praktisk eksempel: URL-shortener service
La oss se på et konkret eksempel på hvordan dette brukes i praksis. Vi skal lage en URL-shortener service med moderne arkitektur.
Først legger vi til prosjektet i config/projects.tfvars
:
Etter merge og godkjenning av de 3 stegene får vi automatisk:
AWS-kontoer:
url-shortener-dev
(123456789012)url-shortener-stage
(123456789013)url-shortener-prod
(123456789014)
GitHub-repositories:
iac-url-shortener
- IaC-repo med miljøer (dev/stage/prod) og AWS-rolle ARNer ferdigkonfigurerturl-shortener-frontend
- React-appenurl-shortener-backend
- API-tjenesten
Og det er alt som trengs 🚀
Resultatet
På 15 minutter har du:
- 3 separate AWS-kontoer med full isolasjon
- 3 GitHub-repos med CI/CD klar til bruk
- Et Terraform-repo klart til å deploye infrastruktur
- Ingen manuell konfigurasjon av AWS-tilganger eller secrets
Du kan umiddelbart begynne å jobbe med applikasjonen, og deployments til dev/stage/prod fungerer fra dag én.
Fra å legge til noen linjer i en konfigurasjonsfil til å ha et fullstendig sett opp prosjekt tar nå rundt 10-15 minutter (mesteparten er venting på at AWS provisjonerer kontoer). Tidligere tok dette flere timer med manuelt arbeid.
Hvert nytt prosjekt får:
- ✅ Dedikerte AWS-kontoer for hvert miljø
- ✅ Korrekt organisasjonsstruktur i AWS
- ✅ GitHub-repositories for kode og infrastruktur
- ✅ Sikker OIDC-autentisering fra GitHub til AWS
- ✅ S3-bøtter for state management
- ✅ Ferdigkonfigurerte miljøvariabler i GitHub
- ✅ En template å starte fra for infrastrukturkode
Alt er klart til å deploye applikasjonen din!
Konklusjon
Ved å bruke OpenTofu (eller Terraform) til å administrere ikke bare applikasjonsinfrastruktur, men også organisasjonsstrukturen og utviklingsverktøyene, kan hele prosessen fra prosjektoppstart til produksjon automatiseres.
Nøkkelen er å tenke på alt som infrastruktur som kode - ikke bare servere og databaser, men også AWS-kontoer, GitHub-repos, og koblingene mellom dem.
OpenTofu sin støtte for dynamisk for_each
på providers gjør denne type løsninger mulig på en måte som ikke er like elegant i vanilla Terraform.
Lykke til med automatiseringen! 🚀
Sjekk ut koden på GitHub!