Last active
April 27, 2025 17:42
-
-
Save gonzalovazquez/e9a0f807bfbe80f07ad384a44ce2337b to your computer and use it in GitHub Desktop.
Terraform file to creating a role for provisioning EKS cluster and resources using OIDC
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Check if OIDC provider exists | |
data "aws_iam_openid_connect_provider" "existing_github" { | |
count = 1 | |
url = "https://token.actions.githubusercontent.com" | |
} | |
# Use existing provider ARN | |
locals { | |
github_oidc_provider_arn = "arn:aws:iam::**********:oidc-provider/token.actions.githubusercontent.com" | |
} | |
# Create IAM role for EKS provisioning and management | |
resource "aws_iam_role" "eks_provisioning" { | |
name = "eks-provisioning-role" | |
assume_role_policy = jsonencode({ | |
Version = "2012-10-17" | |
Statement = [ | |
{ | |
Effect = "Allow" | |
Principal = { | |
Federated = local.github_oidc_provider_arn | |
} | |
Action = "sts:AssumeRoleWithWebIdentity" | |
Condition = { | |
StringEquals = { | |
"token.actions.githubusercontent.com:aud" = "sts.amazonaws.com" | |
} | |
StringLike = { | |
"token.actions.githubusercontent.com:sub" = "repo:gonzalovazquez/argo-cd-eks:*" | |
} | |
} | |
}, | |
{ | |
Effect = "Allow" | |
Principal = { | |
AWS = "arn:aws:iam::::**********:user/Admin" | |
} | |
Action = "sts:AssumeRole" | |
}, | |
{ | |
Effect = "Allow" | |
Principal = { | |
Service = [ | |
"eks.amazonaws.com", | |
"ec2.amazonaws.com" | |
] | |
} | |
Action = [ | |
"sts:AssumeRole", | |
"sts:TagSession" | |
] | |
} | |
] | |
}) | |
} | |
# Attach AWS managed policies | |
resource "aws_iam_role_policy_attachment" "eks_cluster_policy" { | |
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy" | |
role = aws_iam_role.eks_provisioning.name | |
} | |
resource "aws_iam_role_policy_attachment" "eks_block_storage_policy" { | |
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSBlockStoragePolicy" | |
role = aws_iam_role.eks_provisioning.name | |
} | |
resource "aws_iam_role_policy_attachment" "eks_compute_policy" { | |
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSComputePolicy" | |
role = aws_iam_role.eks_provisioning.name | |
} | |
resource "aws_iam_role_policy_attachment" "eks_load_balancing_policy" { | |
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSLoadBalancingPolicy" | |
role = aws_iam_role.eks_provisioning.name | |
} | |
resource "aws_iam_role_policy_attachment" "eks_networking_policy" { | |
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSNetworkingPolicy" | |
role = aws_iam_role.eks_provisioning.name | |
} | |
# Create custom policy for additional permissions | |
resource "aws_iam_policy" "eks_custom_policy" { | |
name = "eks-provisioning-custom-policy" | |
description = "Custom policy for EKS provisioning and management" | |
policy = jsonencode({ | |
Version = "2012-10-17" | |
Statement = [ | |
{ | |
Sid = "GetAuthorizationToken" | |
Effect = "Allow" | |
Action = [ | |
"ecr-public:GetAuthorizationToken", | |
"sts:GetServiceBearerToken" | |
] | |
Resource = "*" | |
}, | |
{ | |
Effect = "Allow" | |
Action = [ | |
"iam:GetRole", | |
"iam:CreateRole", | |
"iam:AttachRolePolicy", | |
"iam:PutRolePolicy", | |
"iam:TagRole", | |
"ec2:CreateVpc", | |
"ec2:DescribeVpcs", | |
"ec2:DescribeVpcAttribute", | |
"ec2:CreateSubnet", | |
"ec2:DescribeSubnets", | |
"ec2:CreateSecurityGroup", | |
"ec2:DescribeSecurityGroups", | |
"ec2:ModifyVpcAttribute", | |
"ec2:DescribeVpcAttribute", | |
"ec2:CreateRouteTable", | |
"ec2:CreateInternetGateway", | |
"ec2:DescribeSecurityGroupRules", | |
"ec2:AssociateRouteTable", | |
"ec2:DescribeSecurityGroups", | |
"ec2:DescribeNetworkInterfaces", | |
"ec2:DescribeRouteTables", | |
"ec2:AttachInternetGateway", | |
"ec2:RevokeSecurityGroupEgress", | |
"ec2:CreateNetworkAcl", | |
"ec2:DescribeAddressesAttribute", | |
"eks:CreateCluster", | |
"eks:DeleteCluster", | |
"eks:DescribeCluster", | |
"eks:ListClusters", | |
"eks:UpdateClusterConfig", | |
"eks:UpdateClusterVersion", | |
"eks:CreateNodegroup", | |
"eks:DeleteNodegroup", | |
"eks:DescribeNodegroup", | |
"eks:ListNodegroups", | |
"eks:TagResource", | |
"eks:UntagResource", | |
"s3:CreateBucket", | |
"s3:PutObject", | |
"s3:GetObject", | |
"s3:ListBucket", | |
"s3:DeleteObject", | |
"s3:PutBucketVersioning", | |
"s3:PutEncryptionConfiguration", | |
"dynamodb:CreateTable", | |
"dynamodb:PutItem", | |
"dynamodb:GetItem", | |
"dynamodb:DeleteItem", | |
"dynamodb:Scan", | |
"ec2:AllocateAddress" | |
] | |
Resource = "*" | |
}, | |
# Specific permissions for terraform state management | |
{ | |
Effect = "Allow" | |
Action = [ | |
"s3:GetObject", | |
"s3:PutObject", | |
"s3:DeleteObject", | |
"s3:ListBucket" | |
] | |
Resource = [ | |
"arn:aws:s3:::argocd-infra", | |
"arn:aws:s3:::argocd-infra/*" | |
] | |
}, | |
{ | |
Effect = "Allow" | |
Action = [ | |
"dynamodb:PutItem", | |
"dynamodb:GetItem", | |
"dynamodb:DeleteItem", | |
"dynamodb:DescribeTable" | |
] | |
Resource = "arn:aws:dynamodb:us-east-1:::**********::table/lock-table" | |
}, | |
{ | |
Effect = "Allow" | |
Action = [ | |
"iam:PassRole" | |
] | |
Resource = [ | |
"arn:aws:iam::366579856667:role/argocd-github-oidc", | |
"arn:aws:iam::366579856667:role/eks-provisioning-role", | |
"arn:aws:iam::366579856667:role/eks-*", | |
"arn:aws:iam::366579856667:role/argocd-*" | |
] | |
Condition = { | |
StringEquals = { | |
"iam:PassedToService" = [ | |
"ec2.amazonaws.com", | |
"eks.amazonaws.com", | |
"autoscaling.amazonaws.com" | |
] | |
} | |
} | |
}, | |
# Additional permissions for your specific terraform config | |
{ | |
Effect = "Allow" | |
Action = [ | |
"ec2:CreateVpcEndpoint", | |
"ec2:DeleteVpcEndpoint", | |
"ec2:DescribeVpcEndpoints", | |
"ec2:ModifyVpcEndpoint", | |
"ec2:DescribeVpcEndpointServices", | |
"ec2:CreateNetworkAclEntry", | |
"ec2:DeleteNetworkAclEntry", | |
"ec2:ReplaceNetworkAclEntry", | |
"ec2:DescribeNetworkAcls", | |
"ec2:ReplaceNetworkAclAssociation", | |
"ec2:ModifyInstanceAttribute", | |
"ec2:EnableEbsEncryptionByDefault", | |
"ec2:DisableEbsEncryptionByDefault", | |
"ec2:GetEbsEncryptionByDefault", | |
"ec2:GetEbsDefaultKmsKeyId", | |
"kms:CreateKey", | |
"kms:DescribeKey", | |
"kms:CreateGrant", | |
"kms:ListGrants", | |
"kms:RevokeGrant", | |
"kms:Encrypt", | |
"kms:Decrypt", | |
"kms:GenerateDataKey", | |
"kms:ReEncrypt", | |
"autoscaling:PutScalingPolicy", | |
"autoscaling:DescribePolicies", | |
"autoscaling:DeletePolicy" | |
] | |
Resource = "*" | |
}, | |
# Additional permissions that might be needed but not in the provided policy | |
{ | |
Effect = "Allow" | |
Action = [ | |
"ec2:DeleteVpc", | |
"ec2:DeleteSubnet", | |
"ec2:DeleteSecurityGroup", | |
"ec2:DeleteRouteTable", | |
"ec2:DeleteInternetGateway", | |
"ec2:DeleteNetworkAcl", | |
"ec2:DetachInternetGateway", | |
"ec2:DisassociateRouteTable", | |
"ec2:ReleaseAddress", | |
"ec2:AuthorizeSecurityGroupIngress", | |
"ec2:AuthorizeSecurityGroupEgress", | |
"ec2:RevokeSecurityGroupIngress", | |
"ec2:ModifySubnetAttribute", | |
"ec2:ModifyNetworkInterfaceAttribute", | |
"ec2:CreateRoute", | |
"ec2:DeleteRoute", | |
"ec2:CreateTags", | |
"ec2:DeleteTags", | |
"ec2:DescribeTags", | |
"ec2:DescribeInternetGateways", | |
"ec2:DescribeNetworkAcls", | |
"ec2:DescribeAvailabilityZones", | |
"ec2:DescribeAddresses", | |
"eks:CreateAddon", | |
"eks:DeleteAddon", | |
"eks:DescribeAddon", | |
"eks:UpdateAddon", | |
"eks:ListAddons", | |
"eks:DescribeAddonVersions", | |
"eks:CreateFargateProfile", | |
"eks:DeleteFargateProfile", | |
"eks:DescribeFargateProfile", | |
"eks:ListFargateProfiles", | |
"eks:UpdateNodegroupConfig", | |
"eks:UpdateNodegroupVersion", | |
"eks:ListIdentityProviderConfigs", | |
"eks:ListUpdates", | |
"eks:DescribeUpdate", | |
"iam:DeleteRole", | |
"iam:DetachRolePolicy", | |
"iam:DeleteRolePolicy", | |
"iam:ListRolePolicies", | |
"iam:ListAttachedRolePolicies", | |
"iam:ListInstanceProfiles", | |
"iam:GetInstanceProfile", | |
"iam:CreateInstanceProfile", | |
"iam:DeleteInstanceProfile", | |
"iam:AddRoleToInstanceProfile", | |
"iam:RemoveRoleFromInstanceProfile", | |
"iam:ListInstanceProfilesForRole", | |
"iam:UpdateAssumeRolePolicy", | |
"iam:CreateOpenIDConnectProvider", | |
"iam:DeleteOpenIDConnectProvider", | |
"iam:GetOpenIDConnectProvider", | |
"iam:ListOpenIDConnectProviders", | |
"iam:TagOpenIDConnectProvider", | |
"iam:UntagOpenIDConnectProvider", | |
"iam:CreateServiceLinkedRole", | |
"iam:DeleteServiceLinkedRole", | |
"iam:GetServiceLinkedRoleDeletionStatus", | |
"kms:CreateKey", | |
"kms:CreateAlias", | |
"kms:DeleteAlias", | |
"kms:DescribeKey", | |
"kms:ListKeys", | |
"kms:ListAliases", | |
"kms:EnableKeyRotation", | |
"kms:DisableKeyRotation", | |
"kms:PutKeyPolicy", | |
"kms:GetKeyPolicy", | |
"kms:TagResource", | |
"kms:UntagResource", | |
"kms:ScheduleKeyDeletion", | |
"kms:CancelKeyDeletion", | |
"kms:CreateGrant", | |
"s3:DeleteBucket", | |
"s3:GetBucketLocation", | |
"s3:GetBucketPolicy", | |
"s3:PutBucketPolicy", | |
"s3:DeleteBucketPolicy", | |
"s3:GetBucketAcl", | |
"s3:PutBucketAcl", | |
"s3:GetBucketVersioning", | |
"s3:GetBucketTagging", | |
"s3:PutBucketTagging", | |
"s3:GetBucketPublicAccessBlock", | |
"s3:PutBucketPublicAccessBlock", | |
"s3:GetBucketEncryption", | |
"s3:PutBucketEncryption", | |
"dynamodb:DescribeTable", | |
"dynamodb:DeleteTable", | |
"logs:CreateLogGroup", | |
"logs:CreateLogStream", | |
"logs:PutLogEvents", | |
"logs:DescribeLogGroups", | |
"logs:DescribeLogStreams", | |
"logs:DeleteLogGroup", | |
"logs:PutRetentionPolicy", | |
"logs:TagLogGroup", | |
"logs:UntagLogGroup", | |
"autoscaling:CreateAutoScalingGroup", | |
"autoscaling:DeleteAutoScalingGroup", | |
"autoscaling:DescribeAutoScalingGroups", | |
"autoscaling:UpdateAutoScalingGroup", | |
"autoscaling:CreateLaunchConfiguration", | |
"autoscaling:DeleteLaunchConfiguration", | |
"autoscaling:DescribeLaunchConfigurations", | |
"autoscaling:CreateOrUpdateTags", | |
"autoscaling:DeleteTags", | |
"autoscaling:DescribeTags", | |
"elasticloadbalancing:CreateLoadBalancer", | |
"elasticloadbalancing:DeleteLoadBalancer", | |
"elasticloadbalancing:DescribeLoadBalancers", | |
"elasticloadbalancing:DescribeLoadBalancerAttributes", | |
"elasticloadbalancing:ModifyLoadBalancerAttributes", | |
"elasticloadbalancing:SetSecurityGroups", | |
"elasticloadbalancing:CreateTargetGroup", | |
"elasticloadbalancing:DeleteTargetGroup", | |
"elasticloadbalancing:DescribeTargetGroups", | |
"elasticloadbalancing:ModifyTargetGroup", | |
"elasticloadbalancing:ModifyTargetGroupAttributes", | |
"elasticloadbalancing:CreateListener", | |
"elasticloadbalancing:DeleteListener", | |
"elasticloadbalancing:DescribeListeners", | |
"elasticloadbalancing:ModifyListener", | |
"elasticloadbalancing:AddTags", | |
"elasticloadbalancing:RemoveTags", | |
"ssm:GetParameter", | |
"ssm:GetParameters", | |
"ssm:GetParametersByPath", | |
"ssm:PutParameter", | |
"ssm:DeleteParameter", | |
"ssm:DeleteParameters", | |
"ec2:RunInstances", | |
"ec2:TerminateInstances", | |
"ec2:DescribeInstances", | |
"ec2:CreateLaunchTemplate", | |
"ec2:CreateLaunchTemplateVersion", | |
"ec2:DeleteLaunchTemplate", | |
"ec2:DescribeLaunchTemplates", | |
"ec2:DescribeLaunchTemplateVersions", | |
"ec2:CreateNatGateway", | |
"ec2:DeleteNatGateway", | |
"ec2:DescribeNatGateways", | |
"ec2:CreateKeyPair", | |
"ec2:DeleteKeyPair", | |
"ec2:DescribeKeyPairs", | |
"ec2:DescribeInstanceTypes", | |
"ec2:DescribeAccountAttributes", | |
"ec2:DescribeRegions", | |
"ec2:DescribeVolumes", | |
"ec2:CreateNetworkInterface", | |
"ec2:DeleteNetworkInterface", | |
"ec2:AttachNetworkInterface", | |
"ec2:DetachNetworkInterface" | |
] | |
Resource = "*" | |
} | |
] | |
}) | |
} | |
# Attach the custom policy to the role | |
resource "aws_iam_role_policy_attachment" "eks_custom_policy" { | |
policy_arn = aws_iam_policy.eks_custom_policy.arn | |
role = aws_iam_role.eks_provisioning.name | |
} | |
# Output the role ARN | |
output "eks_provisioning_role_arn" { | |
value = aws_iam_role.eks_provisioning.arn | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment