DNS Filtering Blog: Latest Trends and Updates | DNSFilter

IAM Userless: Streamline AWS Access | DNSFilter

Written by Thomas Schizas | May 29, 2025 7:26:56 PM


Security and scalability are paramount in modern cloud architectures. Amazon Web Services (AWS) Identity and Access Management is a critical tool that helps you manage users, permissions, and access control across AWS services. While Identity and Access Management (IAM) users have traditionally been the go-to approach for granting access to resources, there are significant advantages to moving to IAM roles.

This article will explore why transitioning to roles is a good idea and how to implement that transition, including integrating Okta as your Identity Provider (IdP) and enabling OpenID Connect (OIDC) for user management. We’ll also walk through how to integrate Okta with Github, Atlantis, and AWS for Terraform deployments.

Why Move from IAM Users to IAM Roles?

Security Best Practices

IAM users are tied directly to specific credentials (username/password or access keys) for authentication. Over time, managing these users can lead to security risks, such as unmonitored access keys or weak passwords. IAM roles, on the other hand, are temporary and are used with AWS services, which reduces the attack surface area. Roles don’t require permanent access credentials, improving security.

  • Reduced Credential Management: Roles are assumed dynamically, and temporary security credentials are granted. This minimizes the risks of long-term credentials being compromised.

  • Granular Permissions: Roles allow for more specific permission assignments, ensuring that users or services have just the permissions they need — the principle of least privilege.

  • Seamless Auditing: With roles, all actions are automatically logged under the assumed role, making it easier to track and monitor activity in AWS.

Scalability and Flexibility

Managing IAM users becomes cumbersome at scale, especially when you have large numbers of developers, administrators, or automated processes needing varying levels of access. IAM roles allow you to easily scale user permissions across teams, departments, or even external partners without having to create and manage separate IAM users for each.

Improved Integration with External Identity Providers (IdPs)

By using IAM roles in combination with identity federation services like Okta, you can simplify the management of external users or teams that require access to your AWS resources. Okta provides an Identity-as-a-Service (IDaaS) solution, which allows for centralized user management and security policies across all your applications, including AWS.

How to Transition from IAM Users to IAM Roles in AWS

To implement the transition from IAM users to roles in AWS using Okta as an Identity Provider (IdP) with Terraform, you'll need to define the necessary resources for AWS IAM, Okta, and identity federation in a Terraform configuration file. 

Prior to following the steps outlined below, be sure that the following applies to your environment:

  • AWS account with appropriate permissions to create IAM roles, policies, and identity providers

  • Okta account with an application set up for OpenID Connect (OIDC)

  • Terraform is installed

Step 1: Set Up Okta as the Identity Provider

We'll configure Okta to be used as an OIDC provider for AWS in Terraform. In this step, you will create the OIDC identity provider in AWS using Okta's issuer URL.

provider "aws" {

  region = "us-east-1"  # Adjust the AWS region as needed

}

provider "okta" {

  org_name = "<your-okta-org-name>"

  api_token = "<your-okta-api-token>"

}

# Okta OIDC Application setup (already configured in Okta Admin Console)

data "okta_app_oauth" "aws_oidc" {

  name = "AWS Access"

}

# OIDC Identity Provider in AWS

resource "aws_iam_openid_connect_provider" "okta" {

  url = "https://<your-okta-domain>.okta.com"

  client_id_list = [data.okta_app_oauth.aws_oidc.client_id]

  thumbprint_list = ["<okta-oidc-cert-thumbprint>"]  # You will need to fetch Okta's OIDC certificate thumbprint

  tags = {

    "Name" = "Okta OIDC Identity Provider"

  }

}


Step 2: Create IAM Role for Federated Access

Next, you’ll define the IAM role in AWS that users will assume after being authenticated via Okta’s OIDC tokens. This role will include a trust policy allowing users from Okta to assume the role.

resource "aws_iam_role" "okta_role" {

  name = "OktaRole"

  assume_role_policy = jsonencode({

    Version = "2012-10-17"

    Statement = [

      {

        Effect = "Allow"

        Principal = {

          Federated = aws_iam_openid_connect_provider.okta.arn

        }

        Action = "sts:AssumeRoleWithWebIdentity"

        Condition = {

          StringEquals = {

            "<your-okta-domain>:sub" = "OktaUserGroup"  # Replace with your Okta user group or role claim

          }

        }

      }

    ]

  })

  # Permissions that the role will grant

  policies = [

    aws_iam_policy.s3_full_access.arn  # Example: attach a policy granting full S3 access

  ]

  tags = {

    "Name" = "OktaFederatedRole"

  }

}

 

Step 3: Create IAM Policy for the Role

For this example, we will create a policy granting full S3 access, which can be adjusted according to your use case.

resource "aws_iam_policy" "s3_full_access" {

  name        = "S3FullAccessPolicy"

  description = "Full access to all S3 resources"

  policy      = jsonencode({

    Version = "2012-10-17"

    Statement = [

      {

        Effect = "Allow"

        Action = "s3:*"

        Resource = "*"

      }

    ]

  })

}


Step 4: Configure User Authentication and Role Assumption in Okta

While this part is mainly handled by Okta, the key step here is to ensure that your Okta application for OIDC is configured to issue tokens that AWS can understand. Make sure the Client ID and Client Secret from Okta match the details used in the OIDC provider configuration in AWS.

In Okta, the users will authenticate using the OIDC app you created, and AWS will allow those authenticated users to assume the OktaRole.

Step 5: Assigning the IAM Role to Users

The IAM role is now ready to be assumed by authenticated Okta users. In practice, Okta users will authenticate through the OIDC flow and, upon success, receive temporary credentials that they can use to interact with AWS resources according to the permissions of the role they assumed.

Example of User Role Assumption

In your application or script, users would authenticate against Okta and assume the AWS role programmatically. Here's how you might handle the role assumption with aws sts assume-role-with-web-identity using the AWS CLI or SDK.

aws sts assume-role-with-web-identity \
  --role-arn arn:aws:iam::<AWS_ACCOUNT_ID>:role/OktaRole \
  --role-session-name OktaSession \
  --web-identity-token <okta-id-token>


This command will return temporary credentials (access key, secret key, and session token), which can be used to interact with AWS resources according to the role’s permissions.

Final Terraform Configuration

Here’s the complete Terraform configuration putting everything together:

provider "aws" {

  region = "us-east-1"  # Adjust region as necessary

}

provider "okta" {

  org_name = "<your-okta-org-name>"

  api_token = "<your-okta-api-token>"

}

data "okta_app_oauth" "aws_oidc" {

  name = "AWS Access"

}

resource "aws_iam_openid_connect_provider" "okta" {

  url = "https://<your-okta-domain>.okta.com"

  client_id_list = [data.okta_app_oauth.aws_oidc.client_id]

  thumbprint_list = ["<okta-oidc-cert-thumbprint>"]

  tags = {

    "Name" = "Okta OIDC Identity Provider"

  }

}

resource "aws_iam_policy" "s3_full_access" {

  name        = "S3FullAccessPolicy"

  description = "Full access to all S3 resources"

  policy      = jsonencode({

    Version = "2012-10-17"

    Statement = [

      {

        Effect = "Allow"

        Action = "s3:*"

        Resource = "*"

      }

    ]

  })

}

resource "aws_iam_role" "okta_role" {

  name = "OktaRole"

  assume_role_policy = jsonencode({

    Version = "2012-10-17"

    Statement = [

      {

        Effect = "Allow"

        Principal = {

          Federated = aws_iam_openid_connect_provider.okta.arn

        }

        Action = "sts:AssumeRoleWithWebIdentity"

        Condition = {

          StringEquals = {

            "<your-okta-domain>:sub" = "OktaUserGroup"

          }

        }

      }

    ]

  })

  policies = [

    aws_iam_policy.s3_full_access.arn

  ]

  tags = {

    "Name" = "OktaFederatedRole"

  }

}


By using Okta as an Identity Provider (IdP) for federated access to AWS, and by leveraging IAM roles instead of IAM users, you can significantly improve your security and scalability. Terraform makes the management of your AWS resources more efficient and repeatable, and you can easily integrate Okta to authenticate and manage users.

This setup ensures that your users never need to have long-lived AWS IAM credentials, while still having the necessary permissions to work with AWS resources in a secure, scalable way.

Now lets take this a step further by integrating Okta with AWS IAM roles. This provides several benefits especially for use with tools like GitHub and Atlantis, and it can significantly improve the security, scalability, and automation of your infrastructure deployments.

In this section, we'll explore how this setup can help streamline continuous integration and continuous deployment (CI/CD) workflows, specifically with Terraform and Atlantis for Infrastructure as Code (IaC) on AWS.

Benefits of Using Okta with AWS Roles for GitHub and Atlantis Integration

Centralized User Management

By using Okta as your identity provider (IdP), you can centralize user management for GitHub and Atlantis, ensuring that access is streamlined across your AWS infrastructure. With Okta federated authentication, you can authenticate users and manage permissions through Okta, ensuring only authorized personnel can deploy and modify infrastructure in AWS via Atlantis.

Enhanced Security and Least Privilege

Instead of embedding permanent AWS IAM credentials in the Atlantis or GitHub environment, roles can be assumed dynamically, providing temporary credentials for specific tasks. This reduces the risk of credential leakage or misuse while maintaining the principle of least privilege for each action performed on AWS.

Seamless Role Assumption with Okta

Okta users will authenticate through the OpenID Connect (OIDC) integration, automatically assuming the appropriate IAM roles with minimal configuration. These roles define the permissions needed to deploy infrastructure (such as S3, EC2, Lambda, etc.) in AWS. When combined with Atlantis, Okta authentication provides an effective security model for automating deployments with Terraform.

How to Integrate Okta with GitHub, Atlantis, and AWS for Terraform Deployments

To successfully integrate Okta with GitHub, Atlantis, and AWS, follow these steps:

Step 1: Set Up Okta for Role Assumption in AWS

As we discussed in the previous section, first you need to set up Okta as an OpenID Connect (OIDC) provider in AWS. This step ensures that Okta users can authenticate and assume IAM roles for accessing AWS resources.

Step 2: Create GitHub Access for Okta Users

  • Configure Okta Application for GitHub:
    • In Okta, create an OIDC application that will authenticate users when they push code to GitHub. This is done similarly to how you set up Okta for AWS, but with GitHub as the target application.

    • Client ID and Client Secret will be used by GitHub actions or workflows to authenticate with Okta.

  • Use GitHub Actions for Continuous Deployment: To integrate Okta’s federated authentication into GitHub, you can set up GitHub Actions to authenticate Okta users, assume an IAM role in AWS, and trigger infrastructure deployment via Terraform.

Example of a GitHub Actions workflow:

name: Deploy Infrastructure with Terraform

on:

  push:

    branches:

      - main

jobs:

  terraform:

    runs-on: ubuntu-latest

    steps:

      - name: Checkout code

        uses: actions/checkout@v2


      - name: Set up Terraform

        uses: hashicorp/setup-terraform@v1


      - name: Configure AWS credentials via Okta

        env:

          OKTA_DOMAIN: $

          OKTA_CLIENT_ID: $

          OKTA_CLIENT_SECRET: $

          AWS_REGION: "us-east-1"

        run: |

          # Use Okta's OIDC authentication flow to get the AWS credentials

          okta_access_token=$(curl -X POST https://$OKTA_DOMAIN/oauth2/default/v1/token \

            -d "client_id=$OKTA_CLIENT_ID" \

            -d "client_secret=$OKTA_CLIENT_SECRET" \

            -d "grant_type=client_credentials" \

            -d "scope=aws:sts:assume-role-with-web-identity" | jq -r .access_token)    

          export AWS_ACCESS_KEY_ID=$(aws sts assume-role-with-web-identity \

            --role-arn arn:aws:iam::<AWS_ACCOUNT_ID>:role/OktaRole \

            --role-session-name "GitHubActionSession" \

            --web-identity-token $okta_access_token \

            --query "Credentials.AccessKeyId" \

            --output text)

          export AWS_SECRET_ACCESS_KEY=$(aws sts assume-role-with-web-identity \

            --role-arn arn:aws:iam::<AWS_ACCOUNT_ID>:role/OktaRole \

            --role-session-name "GitHubActionSession" \

            --web-identity-token $okta_access_token \

            --query "Credentials.SecretAccessKey" \

            --output text)

          export AWS_SESSION_TOKEN=$(aws sts assume-role-with-web-identity \

            --role-arn arn:aws:iam::<AWS_ACCOUNT_ID>:role/OktaRole \

            --role-session-name "GitHubActionSession" \

            --web-identity-token $okta_access_token \

            --query "Credentials.SessionToken" \

            --output text)

      - name: Terraform Apply

        run: terraform apply -auto-approve


In this example:

  • GitHub Actions are used to automate the deployment of Terraform scripts whenever there’s a push to the main branch.

  • Okta is used to authenticate the GitHub Action and obtain temporary AWS credentials via the sts:assume-role-with-web-identity operation.

  • These temporary credentials are then used to deploy infrastructure via Terraform.

Step 3: Set Up Atlantis for Automated Terraform Deployments

Atlantis is a tool that automates Terraform workflows for pull requests. It integrates directly with GitHub to trigger Terraform commands (like terraform plan and terraform apply) when a pull request is opened, updated, or merged.

1. Install Atlantis:

First, you'll need to install Atlantis on a server. There are a variety of options for deploying Atlantis (such as using Docker or a pre-configured VM).

2. Configure Atlantis with GitHub:

Atlantis will need access to GitHub, so you’ll configure it to listen to GitHub events. This is done by setting up webhooks in GitHub and providing Atlantis with a GitHub token (which can be securely managed in Okta if necessary).

3. Atlantis Configuration for Terraform:

Once Atlantis is set up, you can configure it to run Terraform commands using IAM roles. Here’s how you can set it up for Okta-based federated authentication:

Atlantis Config Example (atlantis.yaml):

version: 3

projects:

  - name: "aws-infrastructure"

    dir: "terraform/"

    terraform_version: "1.1.0"

    autoplan:

      enabled: true

      when_modified: ["*.tf", "../modules/**/*.tf"]

      except: ["README.md"]

    apply_requirements: ["approved"]

    workflow: "default"

    vpc_id: "${env.VPC_ID}"  # Example of using environment variables

 

4. Atlantis Integration with Okta:

  • In your Atlantis deployment, make sure the environment is configured to use Okta as the authentication mechanism for assuming IAM roles.

  • Atlantis will interact with GitHub pull requests and invoke Terraform commands only after verifying the identity via Okta.

Step 4: GitHub → Atlantis → Terraform with Okta Integration

The complete workflow will look like this:

  1. Developer pushes code to GitHub (with a pull request to the main branch).

  2. GitHub Action triggers the authentication via Okta, assuming the AWS IAM role.

  3. Atlantis listens to the pull request, automatically running terraform plan and terraform apply if the pull request is approved.

  4. AWS Infrastructure is updated based on the Terraform configurations.

A More Secure Infrastructure Deployment Pipeline

Using Okta for federated authentication with AWS IAM roles in conjunction with GitHub and Atlantis creates a secure and automated deployment pipeline for Infrastructure as Code (IaC) using Terraform. This integration provides centralized user management, seamless role assumption, and enhanced security by using short-lived, temporary credentials.

With this setup, your infrastructure deployment pipeline becomes more secure, scalable, and easier to manage, ensuring that only authorized users and actions are able to modify your cloud infrastructure.

Interested in reading more from our Platform team? Check out this recent article: Platform, Fires, and You: Navigating the Fine Line Between Operations and Development