Example IAM and Policies for Terraform

The below code is used to define AWS IAM roles which are going to be used for federated access, which means another application can assume the role. In this case it's Github and a specific repository is enable to assume the role which has a number of IAM policies assigned.

# GitHub Deployer Role

resource "aws_iam_role" "iam-oidc-role" {
  name                 = "prd-clops-net-ss-nhs-uk-iam-dep-role"
  max_session_duration = 3600
  assume_role_policy   = <<EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::588554574523:oidc-provider/token.actions.githubusercontent.com"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringLike": {
                    "token.actions.githubusercontent.com:sub": "repo:emisgroup/emissharedservice_nhs-uk_route53:*"
                }
            }
        }
    ]
}
EOF
}


resource "aws_iam_policy" "iam-gh-deployer-policy-1" {

  name        = "prd-clops-net-ss-nhs-uk-iam-dep-pol-1"
  path        = "/"
  description = "Prod NHS.UK Domain Deployer Policy 1"
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        "Sid" : "VisualEditor0",
        "Effect" : "Allow",
        "Action" : [
          "dynamodb:PutItem",
          "dynamodb:DescribeTable",
          "dynamodb:DeleteItem",
          "dynamodb:GetItem",
          "dynamodb:DescribeContinuousBackups",
          "dynamodb:Scan",
          "dynamodb:ListTagsOfResource",
          "dynamodb:Query",
          "dynamodb:UpdateItem",
          "dynamodb:DescribeTimeToLive"
        ],
        "Resource" : "arn:aws:dynamodb:eu-west-2:${var.aws_account}:table/${var.dynamodb-statelock}"
      },
      {
        "Sid" : "VisualEditor1",
        "Effect" : "Allow",
        "Action" : [
          "iam:CreateInstanceProfile",
          "iam:GetPolicyVersion",
          "iam:TagRole",
          "iam:RemoveRoleFromInstanceProfile",
          "iam:DeletePolicy",
          "iam:CreateRole",
          "iam:AttachRolePolicy",
          "iam:PutRolePolicy",
          "iam:AddRoleToInstanceProfile",
          "iam:ListInstanceProfilesForRole",
          "iam:PassRole",
          "iam:DetachRolePolicy",
          "iam:ListAttachedRolePolicies",
          "iam:ListRolePolicies",
          "iam:CreatePolicyVersion",
          "iam:ListPolicies",
          "iam:DeleteInstanceProfile",
          "iam:GetRole",
          "iam:GetInstanceProfile",
          "iam:GetPolicy",
          "iam:DeleteRole",
          "iam:TagPolicy",
          "iam:CreatePolicy",
          "iam:CreateServiceLinkedRole",
          "iam:ListPolicyVersions",
          "iam:GetRolePolicy",
          "iam:TagInstanceProfile"
        ],
        "Resource" : "*"
      },
      {
        "Sid" : "VisualEditor3",
        "Effect" : "Allow",
        "Action" : [
          "s3:ListBucket",
          "s3:*Object"
        ],
        "Resource" : "arn:aws:s3:::${var.s3-statefile}/state/*"
      },
      {
        "Sid" : "VisualEditor4",
        "Action" : "s3:ListBucket",
        "Effect" : "Allow",
        "Resource" : "arn:aws:s3:::${var.s3-statefile}"
      },
      {
        "Sid" : "VisualEditor5",
        "Effect" : "Allow",
        "Action" : "ssm:GetParameters",
        "Resource" : "*"
      }
    ]
  })
}
# Network Stuff
# GitHub Deployer Role Policy
resource "aws_iam_policy" "iam-gh-deployer-policy-2" {
  name        = "prd-clops-net-ss-nhs-uk-iam-dep-pol-2"
  path        = "/"
  description = "Prod NHS.UK Domain Deployer Policy 2"
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
        {
        "Sid" : "VisualEditor0",
        "Effect" : "Allow",
        "Action" : [
          "ec2:CreateTransitGatewayConnect",
          "ec2:CreateTransitGatewayRouteTable",
          "ec2:ModifyTransitGateway",
          "ec2:DescribeTransitGatewayRouteTableAnnouncements",
          "ec2:RejectTransitGatewayMulticastDomainAssociations",
          "ec2:CreateTransitGatewayConnectPeer",
          "ec2:AcceptTransitGatewayVpcAttachment",
          "ec2:DescribeTransitGatewayConnectPeers",
          "ec2:CreateTransitGateway",
          "ec2:CreateTransitGatewayPrefixListReference",
          "ec2:SearchTransitGatewayRoutes",
          "ec2:CreateTransitGatewayPeeringAttachment",
          "ec2:DeleteTransitGatewayVpcAttachment",
          "ec2:ModifyTransitGatewayPrefixListReference",
          "ec2:CreateTransitGatewayMulticastDomain",
          "ec2:AssociateTransitGatewayRouteTable",
          "ec2:DescribeTransitGatewayMulticastDomains",
          "ec2:RejectTransitGatewayVpcAttachment",
          "ec2:DeleteTransitGatewayRouteTableAnnouncement",
          "ec2:DisassociateTransitGatewayRouteTable",
          "ec2:DisassociateTransitGatewayPolicyTable",
          "ec2:DisableTransitGatewayRouteTablePropagation",
          "ec2:DeleteTransitGatewayPeeringAttachment",
          "ec2:DeregisterTransitGatewayMulticastGroupMembers",
          "ec2:CreateTransitGatewayRouteTableAnnouncement",
          "ec2:GetTransitGatewayAttachmentPropagations",
          "ec2:CreateTransitGatewayPolicyTable",
          "ec2:DeleteTransitGatewayRouteTable",
          "ec2:CreateTransitGatewayRoute",
          "ec2:DeleteTransitGatewayRoute",
          "ec2:DescribeTransitGatewayAttachments",
          "ec2:CreateTransitGatewayVpcAttachment",
          "ec2:GetTransitGatewayRouteTablePropagations",
          "ec2:EnableTransitGatewayRouteTablePropagation",
          "ec2:DeleteTransitGateway",
          "ec2:DescribeTransitGatewayPeeringAttachments",
          "ec2:DescribeTransitGatewayPolicyTables",
          "ec2:DeleteTransitGatewayPrefixListReference",
          "ec2:ExportTransitGatewayRoutes",
          "ec2:DeleteTransitGatewayPolicyTable",
          "ec2:AcceptTransitGatewayPeeringAttachment",
          "ec2:DescribeTransitGateways",
          "ec2:ReplaceTransitGatewayRoute",
          "ec2:DeleteTransitGatewayMulticastDomain",
          "ec2:GetTransitGatewayPolicyTableEntries",
          "ec2:RejectTransitGatewayPeeringAttachment",
          "ec2:RegisterTransitGatewayMulticastGroupSources",
          "ec2:DescribeTransitGatewayRouteTables",
          "ec2:DeregisterTransitGatewayMulticastGroupSources",
          "ec2:SearchTransitGatewayMulticastGroups",
          "ec2:GetTransitGatewayRouteTableAssociations",
          "ec2:DeleteTransitGatewayConnectPeer",
          "ec2:ModifyTransitGatewayVpcAttachment",
          "ec2:DisassociateTransitGatewayMulticastDomain",
          "ec2:AssociateTransitGatewayMulticastDomain",
          "ec2:GetTransitGatewayPrefixListReferences",
          "ec2:DescribeTransitGatewayConnects",
          "ec2:RegisterTransitGatewayMulticastGroupMembers",
          "ec2:AssociateTransitGatewayPolicyTable",
          "ec2:DeleteTransitGatewayConnect",
          "ec2:DescribeTransitGatewayVpcAttachments",
          "ec2:GetTransitGatewayPolicyTableAssociations",
          "ec2:GetTransitGatewayMulticastDomainAssociations",
          "ec2:AcceptTransitGatewayMulticastDomainAssociations",
          "ec2:CreateFlowLogs"
        ],
        "Resource" : "*"
    }, 
    {
        "Sid" : "VisualEditor1",
        "Effect" : "Allow",
        "Action" : [
          "ec2:DeleteSubnet",
          "ec2:AuthorizeSecurityGroupIngress",
          "ec2:DescribeInstances",
          "ec2:DeleteVpcEndpoints",
          "ec2:CreateTransitGatewayRouteTable",
          "ec2:AttachInternetGateway",
          "ec2:CreateTransitGateway",
          "ec2:DeleteRouteTable",
          "ec2:AssociateRouteTable",
          "ec2:DescribeInternetGateways",
          "ec2:SearchTransitGatewayRoutes",
          "ec2:DeleteTransitGatewayVpcAttachment",
          "ec2:CreateRoute",
          "ec2:CreateInternetGateway",
          "ec2:RevokeSecurityGroupEgress",
          "ec2:DescribeVolumes",
          "ec2:AssociateTransitGatewayRouteTable",
          "ec2:DeleteInternetGateway",
          "ec2:DeleteVpnConnection",
          "ec2:DescribeNetworkAcls",
          "ec2:DescribeRouteTables",
          "ec2:DisassociateTransitGatewayRouteTable",
          "ec2:DisableTransitGatewayRouteTablePropagation",
          "ec2:DescribeVpnConnections",
          "ec2:CreateTags",
          "ec2:CreateRouteTable",
          "ec2:DeleteNetworkInterface",
          "ec2:RunInstances",
          "ec2:CreateCustomerGateway",
          "ec2:DetachInternetGateway",
          "ec2:DescribePrefixLists",
          "ec2:DisassociateRouteTable",
          "ec2:DescribeInstanceCreditSpecifications",
          "ec2:DeleteTransitGatewayRouteTable",
          "ec2:CreateNetworkInterface",
          "ec2:CreateTransitGatewayRoute",
          "ec2:DeleteTransitGatewayRoute",
          "ec2:CreateTransitGatewayVpcAttachment",
          "ec2:DescribeTransitGatewayAttachments",
          "ec2:DescribeSecurityGroupRules",
          "ec2:GetTransitGatewayRouteTablePropagations",
          "ec2:DescribeInstanceTypes",
          "ec2:DescribeVpcEndpoints",
          "ec2:DeleteVpc",
          "ec2:EnableTransitGatewayRouteTablePropagation",
          "ec2:CreateSubnet",
          "ec2:DeleteTransitGateway",
          "ec2:AssociateAddress",
          "ec2:DescribeSubnets",
          "ec2:ModifyVpcEndpoint",
          "ec2:CreateVpnConnection",
          "ec2:DisassociateAddress",
          "ec2:DescribeAddresses",
          "ec2:DeleteTags",
          "ec2:DescribeInstanceAttribute",
          "ec2:ModifyVpnConnection",
          "ec2:CreateVpc",
          "ec2:DescribeTransitGateways",
          "ec2:DescribeAddressesAttribute",
          "ec2:DescribeVpcAttribute",
          "ec2:DescribeNetworkInterfaces",
          "ec2:DescribeTransitGatewayRouteTables",
          "ec2:CreateSecurityGroup",
          "ec2:ModifyVpcAttribute",
          "ec2:ModifyInstanceAttribute",
          "ec2:GetTransitGatewayRouteTableAssociations",
          "ec2:ReleaseAddress",
          "ec2:AuthorizeSecurityGroupEgress",
          "ec2:TerminateInstances",
          "ec2:DetachNetworkInterface",
          "ec2:DescribeTags",
          "ec2:DescribeCustomerGateways",
          "ec2:DescribeSecurityGroups",
          "ec2:AllocateAddress",
          "ec2:DeleteCustomerGateway",
          "ec2:CreateVpcEndpoint",
          "ec2:DescribeVpcs",
          "ec2:DeleteSecurityGroup",
          "ec2:AttachNetworkInterface",
          "ec2:DescribeTransitGatewayVpcAttachments",
          "ec2:RevokeSecurityGroupIngress"
        ],
        "Resource" : "*"
    }
    ]})
}
# DNS Stuff
resource "aws_iam_policy" "iam-gh-deployer-policy-3" {
  name        = "prd-clops-net-ss-nhs-uk-iam-dep-pol-3"
  path        = "/"
  description = "Prod NHS.UK Domain Deployer Policy 3"

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid    = "Route53HostedZoneAndRecords"
        Effect = "Allow"
        Action = [
          "route53:CreateHostedZone",
          "route53:DeleteHostedZone",
          "route53:GetHostedZone",
          "route53:ListHostedZones",
          "route53:UpdateHostedZoneComment",
          "route53:ListHostedZonesByName",
          "route53:GetHostedZoneCount",
          "route53:ChangeResourceRecordSets",
          "route53:ListResourceRecordSets"
        ]
        Resource = "*"
      },
      {
        Sid    = "Route53ResolverManagement"
        Effect = "Allow"
        Action = [
          "route53resolver:CreateResolverEndpoint",
          "route53resolver:DeleteResolverEndpoint",
          "route53resolver:GetResolverEndpoint",
          "route53resolver:ListResolverEndpoints",
          "route53resolver:UpdateResolverEndpoint",
          "route53resolver:AssociateResolverRule",
          "route53resolver:DisassociateResolverRule",
          "route53resolver:CreateResolverRule",
          "route53resolver:DeleteResolverRule",
          "route53resolver:GetResolverRule",
          "route53resolver:ListResolverRules",
          "route53resolver:UpdateResolverRule"
        ]
        Resource = "*"
      }
    ]
  })
}


resource "aws_iam_role_policy_attachment" "iam-attach-perms-policy-1" {
  role       = aws_iam_role.iam-oidc-role.name
  policy_arn = aws_iam_policy.iam-gh-deployer-policy-1.arn
}

resource "aws_iam_role_policy_attachment" "iam-attach-perms-policy-2" {
  role       = aws_iam_role.iam-oidc-role.name
  policy_arn = aws_iam_policy.iam-gh-deployer-policy-2.arn
}

resource "aws_iam_role_policy_attachment" "iam-attach-perms-policy-3" {
  role       = aws_iam_role.iam-oidc-role.name
  policy_arn = aws_iam_policy.iam-gh-deployer-policy-3.arn
}

Last updated