# Data sources
data "aws_caller_identity" "current" {}
data "aws_region" "current" {}
# =============================================================================
# Agent Execution Role — assumed by AgentCore Runtime
# =============================================================================
resource "aws_iam_role" "agent_execution" {
name = "${var.project_name}-${var.environment}-agent-execution"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Sid = "AllowAgentCoreAssumeRole"
Effect = "Allow"
Principal = {
Service = "bedrock-agentcore.amazonaws.com"
}
Action = "sts:AssumeRole"
Condition = {
StringEquals = {
"aws:SourceAccount" = data.aws_caller_identity.current.id
}
ArnLike = {
"aws:SourceArn" = "arn:aws:bedrock-agentcore:${data.aws_region.current.id}:${data.aws_caller_identity.current.id}:*"
}
}
}]
})
}
# Inline policy — least-privilege permissions for the agent execution role
resource "aws_iam_role_policy" "agent_execution" {
name = "AgentCoreExecutionPolicy"
role = aws_iam_role.agent_execution.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
# ECR image pull
{
Sid = "ECRImageAccess"
Effect = "Allow"
Action = [
"ecr:BatchGetImage",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchCheckLayerAvailability"
]
Resource = aws_ecr_repository.mcp_server.arn
},
{
Sid = "ECRTokenAccess"
Effect = "Allow"
Action = ["ecr:GetAuthorizationToken"]
Resource = "*"
},
# CloudWatch Logs
{
Sid = "CloudWatchLogs"
Effect = "Allow"
Action = [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:DescribeLogGroups",
"logs:DescribeLogStreams",
"logs:PutLogEvents"
]
Resource = "arn:aws:logs:${data.aws_region.current.id}:${data.aws_caller_identity.current.id}:log-group:/aws/bedrock-agentcore/runtimes/*"
},
# X-Ray tracing
{
Sid = "XRayTracing"
Effect = "Allow"
Action = [
"xray:PutTraceSegments",
"xray:PutTelemetryRecords",
"xray:GetSamplingRules",
"xray:GetSamplingTargets"
]
Resource = "*"
},
# Secrets Manager — scoped to the specific GitHub PAT secret
{
Sid = "SecretsManagerGetGitHubPAT"
Effect = "Allow"
Action = [
"secretsmanager:GetSecretValue"
]
Resource = aws_secretsmanager_secret.github_pat.arn
},
# Workload access tokens
{
Sid = "WorkloadAccessTokens"
Effect = "Allow"
Action = [
"bedrock-agentcore:GetWorkloadAccessToken",
"bedrock-agentcore:GetWorkloadAccessTokenForJWT",
"bedrock-agentcore:GetWorkloadAccessTokenForUserId"
]
Resource = [
"arn:aws:bedrock-agentcore:${data.aws_region.current.id}:${data.aws_caller_identity.current.id}:workload-identity-directory/default",
"arn:aws:bedrock-agentcore:${data.aws_region.current.id}:${data.aws_caller_identity.current.id}:workload-identity-directory/default/workload-identity/*"
]
}
]
})
}
# =============================================================================
# GitHub Actions OIDC Federation — for CI/CD pipeline authentication
# =============================================================================
# Reference existing OIDC provider (shared across repos in this account)
data "aws_iam_openid_connect_provider" "github_actions" {
url = "https://token.actions.githubusercontent.com"
}
# IAM role assumed by GitHub Actions via OIDC federation
resource "aws_iam_role" "github_actions" {
name = "${var.project_name}-${var.environment}-github-actions"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Sid = "AllowGitHubActionsOIDC"
Effect = "Allow"
Principal = {
Federated = data.aws_iam_openid_connect_provider.github_actions.arn
}
Action = "sts:AssumeRoleWithWebIdentity"
Condition = {
StringEquals = {
"token.actions.githubusercontent.com:aud" = "sts.amazonaws.com"
}
StringLike = {
"token.actions.githubusercontent.com:sub" = "repo:${var.github_repo}:ref:refs/heads/main"
}
}
}]
})
}
# Inline policy — Terraform state access, ECR push, AgentCore management
resource "aws_iam_role_policy" "github_actions" {
name = "GitHubActionsPolicy"
role = aws_iam_role.github_actions.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
# Terraform state — S3 access
{
Sid = "TerraformStateS3"
Effect = "Allow"
Action = [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:ListBucket"
]
Resource = [
"arn:aws:s3:::github-mcp-agentcore-tfstate",
"arn:aws:s3:::github-mcp-agentcore-tfstate/*"
]
},
# Terraform state — DynamoDB lock table
{
Sid = "TerraformStateLock"
Effect = "Allow"
Action = [
"dynamodb:GetItem",
"dynamodb:PutItem",
"dynamodb:DeleteItem"
]
Resource = "arn:aws:dynamodb:${data.aws_region.current.id}:${data.aws_caller_identity.current.id}:table/github-mcp-agentcore-tflock"
},
# ECR — push images
{
Sid = "ECRPush"
Effect = "Allow"
Action = [
"ecr:BatchGetImage",
"ecr:BatchCheckLayerAvailability",
"ecr:CompleteLayerUpload",
"ecr:GetDownloadUrlForLayer",
"ecr:InitiateLayerUpload",
"ecr:PutImage",
"ecr:UploadLayerPart"
]
Resource = aws_ecr_repository.mcp_server.arn
},
{
Sid = "ECRAuth"
Effect = "Allow"
Action = ["ecr:GetAuthorizationToken"]
Resource = "*"
},
# AgentCore — manage runtimes
{
Sid = "AgentCoreManagement"
Effect = "Allow"
Action = [
"bedrock-agentcore:CreateAgentRuntime",
"bedrock-agentcore:UpdateAgentRuntime",
"bedrock-agentcore:DeleteAgentRuntime",
"bedrock-agentcore:GetAgentRuntime",
"bedrock-agentcore:ListAgentRuntimes",
"bedrock-agentcore:ListTagsForResource",
"bedrock-agentcore:TagResource",
"bedrock-agentcore:UntagResource"
]
Resource = "arn:aws:bedrock-agentcore:${data.aws_region.current.id}:${data.aws_caller_identity.current.id}:*"
},
# IAM — manage roles and policies created by Terraform
{
Sid = "IAMPassRole"
Effect = "Allow"
Action = ["iam:PassRole"]
Resource = aws_iam_role.agent_execution.arn
},
# Secrets Manager — Terraform needs to manage the secret resource
{
Sid = "SecretsManagerManage"
Effect = "Allow"
Action = [
"secretsmanager:CreateSecret",
"secretsmanager:DeleteSecret",
"secretsmanager:DescribeSecret",
"secretsmanager:GetSecretValue",
"secretsmanager:PutSecretValue",
"secretsmanager:UpdateSecret",
"secretsmanager:GetResourcePolicy",
"secretsmanager:ListSecretVersionIds",
"secretsmanager:TagResource",
"secretsmanager:UntagResource"
]
Resource = aws_secretsmanager_secret.github_pat.arn
},
# VPC — Terraform needs to manage VPC endpoints and security groups
{
Sid = "VPCEndpointManagement"
Effect = "Allow"
Action = [
"ec2:CreateVpcEndpoint",
"ec2:DeleteVpcEndpoints",
"ec2:DescribeVpcEndpoints",
"ec2:ModifyVpcEndpoint",
"ec2:CreateSecurityGroup",
"ec2:DeleteSecurityGroup",
"ec2:AuthorizeSecurityGroupIngress",
"ec2:RevokeSecurityGroupIngress",
"ec2:AuthorizeSecurityGroupEgress",
"ec2:RevokeSecurityGroupEgress",
"ec2:DescribeSecurityGroups",
"ec2:DescribeVpcs",
"ec2:DescribeSubnets",
"ec2:DescribeNetworkInterfaces",
"ec2:DescribePrefixLists",
"ec2:CreateTags",
"ec2:DeleteTags"
]
Resource = "*"
},
# CloudWatch — Terraform needs to manage log groups and delivery
{
Sid = "CloudWatchManagement"
Effect = "Allow"
Action = [
"logs:CreateLogGroup",
"logs:DeleteLogGroup",
"logs:DescribeLogGroups",
"logs:PutRetentionPolicy",
"logs:TagLogGroup",
"logs:TagResource",
"logs:UntagResource",
"logs:ListTagsForResource",
"logs:ListTagsLogGroup",
"logs:CreateLogDelivery",
"logs:DeleteLogDelivery",
"logs:DescribeLogDeliveries",
"logs:GetLogDelivery",
"logs:PutDeliveryDestination",
"logs:GetDeliveryDestination",
"logs:PutDeliverySource",
"logs:GetDeliverySource",
"logs:CreateDelivery",
"logs:DeleteDelivery",
"logs:GetDelivery",
"logs:DescribeDeliveries",
"logs:DescribeDeliveryDestinations",
"logs:DescribeDeliverySources",
"logs:DeleteDeliveryDestination",
"logs:DeleteDeliverySource"
]
Resource = "*"
},
# X-Ray — Terraform needs to manage trace configuration
{
Sid = "XRayManagement"
Effect = "Allow"
Action = [
"xray:GetGroup",
"xray:CreateGroup",
"xray:DeleteGroup"
]
Resource = "*"
},
# ECR — Terraform needs to manage repository lifecycle and policies
{
Sid = "ECRManagement"
Effect = "Allow"
Action = [
"ecr:CreateRepository",
"ecr:DeleteRepository",
"ecr:DescribeRepositories",
"ecr:SetRepositoryPolicy",
"ecr:GetRepositoryPolicy",
"ecr:DeleteRepositoryPolicy",
"ecr:PutLifecyclePolicy",
"ecr:GetLifecyclePolicy",
"ecr:DeleteLifecyclePolicy",
"ecr:PutImageScanningConfiguration",
"ecr:TagResource",
"ecr:UntagResource",
"ecr:ListTagsForResource"
]
Resource = aws_ecr_repository.mcp_server.arn
},
# IAM — Terraform needs to manage roles and policies it creates
{
Sid = "IAMManagement"
Effect = "Allow"
Action = [
"iam:CreateRole",
"iam:DeleteRole",
"iam:GetRole",
"iam:UpdateRole",
"iam:PutRolePolicy",
"iam:GetRolePolicy",
"iam:DeleteRolePolicy",
"iam:ListRolePolicies",
"iam:ListAttachedRolePolicies",
"iam:TagRole",
"iam:UntagRole"
]
Resource = [
"arn:aws:iam::${data.aws_caller_identity.current.id}:role/${var.project_name}-${var.environment}-*"
]
},
# IAM — read OIDC provider (shared, not managed by this project)
{
Sid = "IAMOIDCProviderRead"
Effect = "Allow"
Action = [
"iam:ListOpenIDConnectProviders",
"iam:GetOpenIDConnectProvider"
]
Resource = "*"
}
]
})
}