Skip to main content
Version: v1.1

IAM Roles and Policies

AosCloud uses IAM roles at multiple levels — EKS Pod Identity or IRSA (IAM Roles for Service Accounts) for Kubernetes pods, EKS system roles for cluster components, and admin roles for infrastructure management. This page documents every role, its trust policy, and the precise permissions it requires.

Prerequisites

Before configuring IAM roles:

  • Review Required AWS Services to understand which AWS services the roles need to access
  • Confirm your AWS account has permission to create IAM roles, policies, and OIDC identity providers
  • Identify any organizational permission boundaries (SCPs, permission boundaries) that may constrain role creation

Pod-to-AWS Authentication

AosCloud supports two mechanisms for granting Kubernetes pods access to AWS services:

The modern approach. EKS Pod Identity simplifies IAM role association without requiring an OIDC identity provider. It uses the EKS Pod Identity Agent (a DaemonSet) to issue credentials to pods.

Key benefits over IRSA:

  • No OIDC provider management — configured directly through the EKS API
  • Single pods.eks.amazonaws.com trust principal for all clusters
  • Credentials assumed once per node (more scalable)
  • Cleaner separation of duties between cluster and IAM administration

Trust policy pattern:

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "pods.eks.amazonaws.com"
},
"Action": [
"sts:AssumeRole",
"sts:TagSession"
]
}
]
}

Setup: Install the EKS Pod Identity Agent addon, then create Pod Identity associations via the EKS API linking service accounts to IAM roles.

IRSA — IAM Roles for Service Accounts (Legacy)

The legacy approach. IRSA relies on an OpenID Connect (OIDC) identity provider that links Kubernetes service accounts to IAM roles via web identity federation.

Service Accounts (Application Workloads)

These roles are assumed by Kubernetes pods running AosCloud microservices. Each is bound to a specific service account name and grants only the AWS permissions that workload requires.

IRSA Trust Policy Pattern

When using IRSA, all application roles use a common trust policy pattern:

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRoleWithWebIdentity",
"Principal": {
"Federated": "<OIDC-provider-ARN>"
},
"Condition": {
"StringLike": {
"<OIDC-issuer-URL>:sub": "system:serviceaccount:*:<service-account-name>"
}
}
}
]
}

The StringLike condition with wildcard namespace (*) allows the service account to function across namespaces during development. For production hardening, replace with StringEquals and a specific namespace.

Service Account Inventory

Service AccountNaming PatternUsed ByNamespace
sa_app{project}-{env}-appAPI, Auth, and Frontend pods{environment}
sa_task{project}-{env}-taskBackend task workers, Message Handler{environment}
sa_sd{project}-{env}-sdService Discovery pods{environment}
sa_secrets_manager{project}-{env}-secrets-managerSecrets CSI driver pods{environment}
sa_base{project}-{env}-baseCore platform pods (broad access){environment}
sa_data_services{project}-{env}-data-servicesData service pods{environment}
sa_uqm{project}-{env}-qmUnit monitoring pods{environment}

Permissions by Service Account

sa_app — Application Pods

PolicyAWS ActionsResourcesPurpose
default_backendS3: GetObject, PutObject, DeleteObject, ListBucket; KMS: Encrypt, Decrypt, GenerateDataKeyBackend S3 bucket, KMS keyRead/write Deployable Items and application data

sa_task — Task Workers and Message Handler

PolicyAWS ActionsResourcesPurpose
ec2_taskEC2: RunInstances, DescribeInstances, DescribeLaunchTemplates, CreateTags, TerminateInstancesEC2 instances with tag managedby=aos-appManage EC2 instances for Unit image building
default_backendS3 + KMS read/writeBackend S3 bucketAccess Deployable Items
secrets_manager_rwSecrets Manager: full CRUD; KMS: Encrypt, DecryptSecrets at path {project}-{env}*Manage application secrets

sa_sd — Service Discovery

PolicyAWS ActionsResourcesPurpose
default_backendS3 + KMS read/writeBackend S3 bucketAccess service configuration data

sa_secrets_manager — Secrets CSI Provider

PolicyAWS ActionsResourcesPurpose
secrets_manager_rwSecrets Manager: GetSecretValue, CreateSecret, UpdateSecret, DeleteSecret, ListSecrets; KMS: Encrypt, Decrypt, GenerateDataKeySecrets at path {project}-{env}*, KMS keyMount secrets as volumes in pods via CSI driver

sa_base — Core Platform (Broadest Privileges)

PolicyAWS ActionsResourcesPurpose
default_backendS3 + KMS read/writeBackend S3 bucketApplication data
secrets_manager_rwSecrets Manager + KMS full accessSecrets at path {project}-{env}*Secret management
ec2_taskEC2 instance lifecycleTagged EC2 instancesImage building
s3_infraS3 + KMS read/writeInfrastructure S3 bucketInfrastructure artifacts
saasaws-marketplace:ResolveCustomer, BatchMeterUsage, GetEntitlements; sts:AssumeRole; sqs:*Marketplace resources, SaaS role ARNAWS Marketplace SaaS integration
CloudWatchAgentServerPolicyCloudWatch Logs and Metrics publishingAll resourcesMetrics and log forwarding

sa_data_services — Data Services

PolicyAWS ActionsResourcesPurpose
default_backendS3 + KMS read/writeBackend S3 bucketData persistence

sa_uqm — Unit Monitoring

PolicyAWS ActionsResourcesPurpose
default_backendS3 + KMS read/writeBackend S3 bucketMonitoring data storage
ec2_taskEC2 instance operationsTagged EC2 instancesFleet monitoring operations

Service Accounts (EKS System Components)

These roles serve Kubernetes system components. They operate in the kube-system namespace.

System Service Account Inventory

Service AccountRole Name PatternKubernetes IdentityPolicies
Cluster Autoscaler{cluster}-autoscaling-rolekube-system:aws-node, kube-system:cluster-autoscalerCustom autoscaler policy
AWS Load Balancer Controller{cluster}-load-balancer-controllerkube-system:aws-load-balancer-controllerCustom LB controller policy
EBS CSI Driver{cluster}-ebs-controllerkube-system:ebs-csi-*AmazonEBSCSIDriverPolicy (AWS-managed)
EFS CSI Driver{cluster}-efs-controllerkube-system:efs-csi*AmazonEFSCSIDriverPolicy (AWS-managed)
VPC CNI{cluster}-vpc-cni-controllerkube-system:aws-node*AmazonEKS_CNI_Policy (AWS-managed)

Cluster Autoscaler Permissions

{
"Statement": [
{
"Sid": "clusterAutoscalerAll",
"Effect": "Allow",
"Action": [
"autoscaling:DescribeAutoScalingGroups",
"autoscaling:DescribeAutoScalingInstances",
"autoscaling:DescribeInstances",
"autoscaling:DescribeLaunchConfigurations",
"autoscaling:DescribeTags",
"autoscaling:SetDesiredCapacity",
"autoscaling:TerminateInstanceInAutoScalingGroup",
"ec2:DescribeLaunchTemplateVersions",
"ec2:DescribeInstanceTypes",
"ec2:DescribeImages",
"ec2:GetInstanceTypesFromInstanceRequirements",
"eks:DescribeNodegroup"
],
"Resource": "*"
},
{
"Sid": "clusterAutoscalerOwn",
"Effect": "Allow",
"Action": [
"autoscaling:SetDesiredCapacity",
"autoscaling:TerminateInstanceInAutoScalingGroup",
"autoscaling:UpdateAutoScalingGroup"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"autoscaling:ResourceTag/k8s.io/cluster-autoscaler/${CLUSTER_ID}": "owned",
"autoscaling:ResourceTag/k8s.io/cluster-autoscaler/enabled": "true"
}
}
}
]
}

The second statement restricts mutating operations to Auto Scaling groups owned by this specific cluster.

AWS Load Balancer Controller Permissions

The LB controller requires broad read access to EC2/ELB resources plus write access to manage load balancers and target groups. Key actions include:

  • ec2:Describe* — discover VPCs, subnets, security groups
  • elasticloadbalancing:* — full ALB/NLB lifecycle management
  • iam:CreateServiceLinkedRole — for ELB service-linked role (conditioned on elasticloadbalancing.amazonaws.com)
  • cognito-idp:DescribeUserPoolClient — for Cognito-authenticated ALBs
  • wafv2:*, shield:* — WAF and Shield association with ALBs
  • acm:DescribeCertificate, acm:ListCertificates — TLS certificate discovery

The LB controller policy is comprehensive — see the AWS Load Balancer Controller documentation for the full IAM policy reference.

EKS Cluster Roles

Control Plane Role

PropertyValue
Name pattern{cluster}-role
Trust principaleks.amazonaws.com
Managed policiesAmazonEKSClusterPolicy, AmazonEKSServicePolicy, AmazonEKSVPCResourceController
PurposeAllows the EKS control plane to manage AWS resources on behalf of the cluster

Node Group Role

PropertyValue
Name pattern{cluster}-node-role
Trust principalec2.amazonaws.com
Managed policiesAmazonEKSWorkerNodePolicy, AmazonEKS_CNI_Policy, CloudWatchAgentServerPolicy, AmazonEC2ContainerRegistryReadOnly, AmazonEC2ContainerRegistryPowerUser
PurposeGrants worker nodes permissions to join the cluster, pull container images, and publish logs

Permission Boundaries

All roles created by the infrastructure support an optional permission boundary. When set, every role (service accounts, EKS) cannot exceed the permissions defined in the boundary policy, regardless of what policies are attached.

This is useful for organizations with central security teams that enforce guardrails on delegated IAM role creation.

IAM Policy Templates Reference

The infrastructure uses parameterized JSON policy templates. Below is a summary of each custom policy:

Policy TemplateParametersScope
policy-rw-s3.jsonBUCKET, KMS_KEY_ARNS3 read/write + KMS encrypt/decrypt on a specific bucket
policy-secrets-manager.jsonSECRET_PATH_ARN, KMS_ARNFull Secrets Manager CRUD scoped to a path prefix + KMS operations
policy-ec2-task.jsonREGION, ACCOUNTNUMBER, TAG_KEY, TAG_VALUE, LAUNCH_TEMPLATEEC2 instance lifecycle constrained by tags and launch templates
policy-saas.jsonAWS_SAAS_ARNAWS Marketplace metering + cross-account STS assume

Role Architecture Diagram

Security Recommendations

  1. Use EKS Pod Identity where possible — It's simpler to manage and more scalable than IRSA. IRSA remains supported for system components that don't yet support Pod Identity.
  2. Tighten trust conditions — When using IRSA, replace StringLike with StringEquals and specify exact namespace in production to prevent cross-namespace impersonation
  3. Enable permission boundaries — Set a permission boundary ARN to enforce organizational guardrails
  4. Audit with CloudTrail — All AssumeRoleWithWebIdentity and AssumeRole calls are logged, enabling pod-level attribution of AWS API calls
  5. Scope sa_base down — The base service account has the broadest permissions; consider splitting into more granular roles if your security posture requires it