Skip to content

Instantly share code, notes, and snippets.

@gonzalovazquez
Last active April 27, 2025 17:42
Show Gist options
  • Save gonzalovazquez/e9a0f807bfbe80f07ad384a44ce2337b to your computer and use it in GitHub Desktop.
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
# 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