IDENTITY · AWS, AZURE, GOOGLE CLOUD → STACKIT
Cloud IAM and identity migration to STACKIT
Policies do not migrate; identities do. On STACKIT a machine identity from AWS, Azure or Google Cloud becomes a service account, a person signs in through your organisation's identity provider, and what the identity may do becomes a role assignment that you choose, because StackToIT does not translate cloud actions into STACKIT roles. Three small runs of 4 November 2026 show what the drafts write, what they leave to you and why the access keys are the part to plan first.
How each source identity maps
One row per identity kind, taken from three runs: an 11-resource AWS estate, and a 4-resource estate each for Azure and Google Cloud.
| Source identity | STACKIT target the draft writes | What stays with you |
|---|---|---|
| AWS IAM user with an access key and no console login | A service account, a service account key and project role assignments | The roles, the lifetime of the key and the hand-over of the new key to every caller of the old one |
| AWS IAM role of an EC2 instance, with its instance profile | A service account attached to the server, with role assignments | The roles, and the permission to act as the account when the server is attached |
| AWS IAM group | An identity provider group; the roles are assigned to its members | Who the members are and which roles they get |
| Azure user-assigned managed identity | A service account only; its role assignments are left to a person | Mapping of resource groups to projects, every consumer's code, the roles |
| Google service account with bucket and project bindings | A service account; the bindings are reviewed by a person | The roles, and the code of workloads that used the metadata server |
In the AWS run, 11 resources became 5 units: the policy, the attachments, the membership, the instance profile and the access key are folded into the user, role, group and instance they belong to. Azure and Google Cloud drafts write the principal and leave the grants as open settings. Only the AWS draft wrote role assignment resources.
An instance role becomes an attached service account
Left: an EC2 role and its instance profile as the AWS source declares them. Right: three blocks of the STACKIT draft in identity.tf, with the comment lines above each block left out.
resource "aws_iam_role" "app" {
name = "reports-app"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{ Effect = "Allow", Action = "sts:AssumeRole", Principal = { Service = "ec2.amazonaws.com" } }]
})
}
resource "aws_iam_instance_profile" "app" {
name = "reports-app"
role = aws_iam_role.app.name
}resource "stackit_service_account" "app" {
project_id = var.project_id
name = "app"
}
resource "stackit_authorization_project_role_assignment" "app" {
for_each = toset(var.app_project_roles)
resource_id = var.project_id
role = each.value
subject = stackit_service_account.app.email
}
resource "stackit_server_service_account_attach" "app" {
project_id = var.project_id
region = var.region
server_id = stackit_server.app.server_id
service_account_email = stackit_service_account.app.email
}The roles are a variable
The role assignment reads var.app_project_roles. The variable's description lists what the source policy allows, s3:GetObject and s3:PutObject, and leaves the choice of STACKIT roles to you.
The grant is wider than the policy
The AWS policy named one bucket. A project role assignment applies to the whole project, and the draft says so: use per-resource bindings where the STACKIT service offers them.
The instance profile has no object
The draft notes that STACKIT has no instance profile: the server acts as the attached service account directly, and the trust policy, session duration and permissions boundary of the role are not carried.
Two traps in the attach step
Attaching needs the right to act as the account. The draft records that an attachment answered 403 about half a second after the account was created and 201 about seven seconds later, so retry before you suspect permissions.
An access key becomes a service account key
Left: the CI user with its access key. Right: the service account, its key and the first role assignment from the same draft; comments above each block are left out.
resource "aws_iam_user" "ci" {
name = "ci-deploy"
}
resource "aws_iam_access_key" "ci" {
user = aws_iam_user.ci.name
}resource "stackit_service_account" "ci" {
project_id = var.project_id
name = "ci"
}
resource "stackit_service_account_key" "ci" {
project_id = var.project_id
service_account_email = stackit_service_account.ci.email
ttl_days = var.ci_key_ttl_days
}
resource "stackit_authorization_project_role_assignment" "ci" {
count = length([stackit_service_account.ci.email]) * length(var.ci_project_roles)
resource_id = var.project_id
role = var.ci_project_roles[count.index % length(var.ci_project_roles)]
subject = [stackit_service_account.ci.email][floor(count.index / length(var.ci_project_roles))]
}The key has a lifetime
ttl_days reads var.ci_key_ttl_days. The variable's description notes that the AWS access keys do not expire and that a STACKIT key without ttl_days stays valid until deleted.
The secret never travels
The credential is the sensitive json output of the key, created by STACKIT. The AWS secret is never read or carried, and the new key reaches callers through a manual hand-over step.
The old key stays until the GO
The rollback of the hand-over is to switch the callers back to the AWS key, which stays active until the retirement of the user after the GO decision.
Federation is a question, not a result
The identity transition file marks this user's static credential as observed and workload identity federation as evidence required. The run never claims that federation can replace the key.
Azure: the identity moves, the role assignment waits for a person
Left: a user-assigned managed identity and its blob role assignment. Right: the only block the draft writes for it.
resource "azurerm_user_assigned_identity" "app" {
name = "id-reports-app"
resource_group_name = azurerm_resource_group.app.name
location = azurerm_resource_group.app.location
}
resource "azurerm_role_assignment" "app_blob" {
scope = azurerm_storage_account.reports.id
role_definition_name = "Storage Blob Data Contributor"
principal_id = azurerm_user_assigned_identity.app.principal_id
}resource "stackit_service_account" "app" {
project_id = var.project_id
name = "app"
}Three open settings
The plan asks a person about the resource group scope, the credential-less code and the role assignments. Each Azure role is re-mapped by hand.
Code changes in every consumer
Code that used a managed identity usually holds no credentials at all. On STACKIT it needs service account credentials or workload identity, so every consumer changes, not only the infrastructure.
Where the Google Cloud draft lands
The service account maps the same way, and its e-mail address changes: references to the old address must be updated. The project-level binding is reviewed by a person.
The steps, in order
General practice, tied to the files of a run.
Read the identity transition
assurance/identity-transition.md lists each workload, its static credentials and whether the attachment to a server is exact. It also lists what it does not assess: privilege delta, break-glass access and human identity.
Separate people from workloads
People sign in through the organisation's identity provider, and groups are recreated there. The draft lists the members in a variable and assigns roles per user, service account or client, not per group.
Choose the roles
For each variable such as app_project_roles, list the roles STACKIT offers on the project and choose the narrowest set that covers what the old policy allowed.
Create accounts, then attach
Apply the service accounts and grant the applying principal the permission to act as them. Attach to servers afterwards, and retry once if the first answer is 403.
Hand over keys or switch to federation
Give every caller of an old access key its new credential, or set up a federated identity provider that trusts the caller's OIDC issuer. STACKIT documents that the issuer URL must match the exact iss value of the tokens.
Retire the source identities last
The plan places the retirement of users and roles after the GO decision, so the rollback of a hand-over stays a switch back to the old key.
Decisions the architect owns
Roles per service account
The drafts never derive a STACKIT role from a cloud action. A person chooses, and the scope of the grant is a project unless a service offers finer bindings.
Key or federation
A service account key is a credential, and STACKIT warns that a leaked private key exposes everything the account can access. Federation yields short-lived tokens without static keys but needs an OIDC issuer.
Project layout
STACKIT has no resource group. Where Azure inherited roles through a group, you decide how the boundaries map to projects, folders and roles.
Token flow
STACKIT documents 16 December 2025 as the deprecation date of service account access tokens and offers a guide for moving from the token flow to the key flow. Build new automation on keys or federation.
Questions security teams ask
Can my IAM policies be imported into STACKIT?
No. The drafts write role assignments with the roles as a variable, because an AWS action does not map one to one to a STACKIT role. The source policy appears in the variable's description, and a person translates it.
Does an EC2 instance profile have an equivalent on STACKIT?
The server acts as an attached service account. The draft notes that a metadata token path answered with a token in its tests of 8 and 9 October 2026, while an EC2-style credentials path answered HTTP 500, so code that reads credentials from an instance metadata endpoint changes.
Can I apply the role assignments as written?
They are written with an opt-in feature of the STACKIT Terraform provider that the draft enables in its provider block and the provider documents as likely to change. Review them, and set the roles, before you apply.
What happens to the AWS access key?
It keeps working until you retire it. The plan puts the retirement after the GO decision, so you can switch callers back until then.
Sources
Your next move: STACKIT.
Tell us about your estate. We show you what StackToIT delivers for it: target architecture, Terraform artifacts and a structured migration plan.