OIDC authentication for CI/CD in Terraform - Time & Space Complexity
Start learning this pattern below
Jump into concepts and practice - no test required
We want to understand how the time needed to set up OIDC authentication in CI/CD changes as we add more resources.
How does the work grow when we add more roles or policies in Terraform?
Analyze the time complexity of the following code snippet.
resource "aws_iam_openid_connect_provider" "oidc_provider" {
url = var.oidc_url
client_id_list = ["sts.amazonaws.com"]
thumbprint_list = [var.thumbprint]
}
resource "aws_iam_role" "ci_cd_role" {
count = var.role_count
name = "ci-cd-role-${count.index}"
assume_role_policy = jsonencode({
Statement = [{
Effect = "Allow"
Principal = { Federated = aws_iam_openid_connect_provider.oidc_provider.arn }
Action = "sts:AssumeRoleWithWebIdentity"
}]
})
}
This code creates one OIDC provider and multiple IAM roles for CI/CD, each trusting the provider.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Creating multiple IAM roles using
countto repeat the resource block. - How many times: The number of roles equals
var.role_count, so the role creation repeats that many times.
As you increase the number of roles, Terraform creates more resources one by one.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 10 role creations |
| 100 | 100 role creations |
| 1000 | 1000 role creations |
Pattern observation: The work grows directly with the number of roles you add.
Time Complexity: O(n)
This means the time to create roles grows linearly as you add more roles.
[X] Wrong: "Adding more roles won't affect the time much because Terraform handles it fast."
[OK] Correct: Each role is a separate resource, so more roles mean more work and longer apply times.
Understanding how resource count affects deployment time helps you plan scalable infrastructure and explain your design choices clearly.
"What if we replaced count with for_each using a map of roles? How would the time complexity change?"
Practice
Solution
Step 1: Understand OIDC purpose in CI/CD
OIDC provides a secure way for pipelines to prove identity without passwords.Step 2: Connect to Terraform usage
Terraform can create roles that trust OIDC tokens, avoiding password storage.Final Answer:
It allows secure authentication without storing passwords in the pipeline. -> Option DQuick Check:
OIDC = passwordless secure authentication [OK]
- Thinking OIDC automates deployment without approval
- Confusing OIDC with replacing Terraform
- Assuming OIDC disables access controls
Solution
Step 1: Identify correct OIDC provider ARN format
The OIDC provider ARN for GitHub Actions uses 'token.actions.githubusercontent.com'.Step 2: Check assume_role_policy structure
The policy must allow 'sts:AssumeRoleWithWebIdentity' with Principal as Federated and correct ARN.Final Answer:
The resource block with Federated principal using 'token.actions.githubusercontent.com' and 'sts:AssumeRoleWithWebIdentity' action. -> Option AQuick Check:
Correct OIDC ARN + sts:AssumeRoleWithWebIdentity = resource "aws_iam_role" "github_oidc_role" { assume_role_policy = jsonencode({ Version = "2012-10-17", Statement = [{ Effect = "Allow", Principal = { Federated = "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com" }, Action = "sts:AssumeRoleWithWebIdentity" }] }) } [OK]
- Using Service principal instead of Federated
- Wrong OIDC provider ARN format
- Using sts:AssumeRole instead of sts:AssumeRoleWithWebIdentity
condition = {
StringEquals = {
"token.actions.githubusercontent.com:sub" = "repo:myorg/myrepo:ref:refs/heads/main"
}
}Solution
Step 1: Understand the condition key
The condition uses 'token.actions.githubusercontent.com:sub' to specify the GitHub repo and branch.Step 2: Interpret the value
The value 'repo:myorg/myrepo:ref:refs/heads/main' restricts access to the main branch of that repo only.Final Answer:
Restricts role assumption to the main branch of myorg/myrepo only. -> Option BQuick Check:
Condition limits to specific repo and branch = Restricts role assumption to the main branch of myorg/myrepo only. [OK]
- Ignoring the branch restriction in condition
- Assuming condition allows all repos
- Confusing forks with original repo access
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": { "Federated": "arn:aws:iam::123456789012:oidc-provider/github.com" },
"Action": "sts:AssumeRoleWithWebIdentity"
}]
}
What is the most likely error?Solution
Step 1: Check the OIDC provider ARN
The ARN 'arn:aws:iam::123456789012:oidc-provider/github.com' is incorrect for GitHub Actions.Step 2: Identify correct ARN for GitHub Actions
The correct ARN uses 'token.actions.githubusercontent.com' as the OIDC provider host.Final Answer:
The OIDC provider ARN is incorrect; it should be 'token.actions.githubusercontent.com'. -> Option CQuick Check:
Wrong OIDC ARN causes auth failure = The OIDC provider ARN is incorrect; it should be 'token.actions.githubusercontent.com'. [OK]
- Using 'sts:AssumeRole' instead of 'sts:AssumeRoleWithWebIdentity'
- Confusing Federated with Service principal
- Ignoring ARN format for OIDC provider
Solution
Step 1: Understand the condition key and value
To restrict to the 'release' branch, the condition must match 'repo:myorg/myrepo:ref:refs/heads/release'.Step 2: Choose correct operator
'StringEquals' ensures exact match, so only 'release' branch is allowed.Final Answer:
The condition block with StringEquals matching 'repo:myorg/myrepo:ref:refs/heads/release'. -> Option AQuick Check:
Exact branch match uses StringEquals with correct ref [OK]
- Using StringLike with wildcard allowing all branches
- Checking audience (aud) instead of subject (sub)
- Using StringNotEquals which excludes main but allows others
