Skip to main content

IAM and RBAC Requirements for Multi-Cloud Deployment

Last Updated: 2025-11-02 Applies To: GCP GKE, AWS EKS, Azure AKS Purpose: Comprehensive IAM/RBAC permissions required for CI/CD deployments

Overview

This document defines all required IAM roles, permissions, and RBAC policies needed to deploy MCP Server LangGraph to Kubernetes across all three major cloud providers.

Principle: Least Privilege

All permissions follow the principle of least privilege - granting only the minimum permissions necessary for each operation.

GCP (Google Kubernetes Engine)

Service Account: mcp-staging-sa@PROJECT_ID.iam.gserviceaccount.com

Required IAM Roles

RolePermissionPurposeRequired For
roles/artifactregistry.writerCRITICALPush Docker images to Artifact RegistryDocker build & push
roles/container.developerCRITICALDeploy to GKE, manage workloadskubectl apply, rollout
roles/logging.logWriterStandardWrite application logsRuntime logging
roles/monitoring.metricWriterStandardWrite metrics and tracesObservability
roles/secretmanager.secretAccessorStandardAccess application secretsRuntime configuration
roles/cloudsql.clientOptionalConnect to Cloud SQL databasesDatabase access

Grant Commands

PROJECT_ID="your-project-id"
SERVICE_ACCOUNT="mcp-staging-sa@${PROJECT_ID}.iam.gserviceaccount.com"

# CRITICAL: Artifact Registry Writer
gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:${SERVICE_ACCOUNT}" \
  --role="roles/artifactregistry.writer"

# CRITICAL: Container Developer
gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:${SERVICE_ACCOUNT}" \
  --role="roles/container.developer"

# Standard: Logging
gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:${SERVICE_ACCOUNT}" \
  --role="roles/logging.logWriter"

# Standard: Monitoring
gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:${SERVICE_ACCOUNT}" \
  --role="roles/monitoring.metricWriter"

# Standard: Secrets
gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:${SERVICE_ACCOUNT}" \
  --role="roles/secretmanager.secretAccessor"

# Optional: Cloud SQL (if using managed PostgreSQL)
gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:${SERVICE_ACCOUNT}" \
  --role="roles/cloudsql.client"

Workload Identity Federation (GitHub Actions)

Pool: github-actions-pool Provider: github-provider
# Allow GitHub Actions to impersonate service account
gcloud iam service-accounts add-iam-policy-binding \
  "${SERVICE_ACCOUNT}" \
  --role="roles/iam.workloadIdentityUser" \
  --member="principalSet://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/github-actions-pool/attribute.repository/${GITHUB_REPO}"

Kubernetes RBAC (In-Cluster)

Service Account: mcp-server-langgraph (in namespace)
apiVersion: v1
kind: ServiceAccount
metadata:
  name: mcp-server-langgraph
  namespace: staging-mcp-server-langgraph
  annotations:
    iam.gke.io/gcp-service-account: mcp-staging-sa@PROJECT_ID.iam.gserviceaccount.com

Verification

# Check all IAM roles
gcloud projects get-iam-policy $PROJECT_ID \
  --flatten="bindings[].members" \
  --filter="bindings.members:${SERVICE_ACCOUNT}" \
  --format="table(bindings.role)"

# Expected output:
# roles/artifactregistry.writer     ✓
# roles/container.developer         ✓
# roles/logging.logWriter           ✓
# roles/monitoring.metricWriter     ✓
# roles/secretmanager.secretAccessor ✓
# roles/cloudsql.client             ✓

AWS (Elastic Kubernetes Service)

IAM Role: mcp-eks-deployment-role

Required IAM Policies

PolicyTypePurposeRequired For
AmazonEKSClusterPolicyAWS ManagedEKS cluster managementCluster operations
AmazonEKSServicePolicyAWS ManagedEKS service linkingService integration
AmazonEKSVPCResourceControllerAWS ManagedVPC resource managementNetwork policies
Custom: ECR Push/PullCustomPush/pull container imagesDocker build & push
Custom: EKS DeployCustomDeploy to EKS workloadskubectl apply
Custom: CloudWatch LogsCustomWrite application logsLogging
Custom: CloudWatch MetricsCustomPublish metricsObservability
Custom: Secrets ManagerCustomAccess secretsRuntime config

Custom IAM Policy: ECR Access

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ECRPushPull",
      "Effect": "Allow",
      "Action": [
        "ecr:GetAuthorizationToken",
        "ecr:BatchCheckLayerAvailability",
        "ecr:GetDownloadUrlForLayer",
        "ecr:PutImage",
        "ecr:InitiateLayerUpload",
        "ecr:UploadLayerPart",
        "ecr:CompleteLayerUpload",
        "ecr:BatchGetImage"
      ],
      "Resource": "*"
    }
  ]
}

Custom IAM Policy: EKS Deployment

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "EKSDeploy",
      "Effect": "Allow",
      "Action": [
        "eks:DescribeCluster",
        "eks:ListClusters",
        "eks:DescribeNodegroup",
        "eks:ListNodegroups"
      ],
      "Resource": "arn:aws:eks:*:ACCOUNT_ID:cluster/mcp-*"
    }
  ]
}

IRSA (IAM Roles for Service Accounts)

Service Account Annotation:
apiVersion: v1
kind: ServiceAccount
metadata:
  name: mcp-server-langgraph
  namespace: mcp-server-langgraph
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::ACCOUNT_ID:role/mcp-eks-pod-role
Trust Policy:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::ACCOUNT_ID:oidc-provider/oidc.eks.REGION.amazonaws.com/id/CLUSTER_ID"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "oidc.eks.REGION.amazonaws.com/id/CLUSTER_ID:sub": "system:serviceaccount:mcp-server-langgraph:mcp-server-langgraph"
        }
      }
    }
  ]
}

Grant Commands (AWS CLI)

# Create IAM role for EKS deployment
aws iam create-role \
  --role-name mcp-eks-deployment-role \
  --assume-role-policy-document file://trust-policy.json

# Attach AWS managed policies
aws iam attach-role-policy \
  --role-name mcp-eks-deployment-role \
  --policy-arn arn:aws:iam::aws:policy/AmazonEKSClusterPolicy

# Create and attach custom ECR policy
aws iam put-role-policy \
  --role-name mcp-eks-deployment-role \
  --policy-name ECRAccess \
  --policy-document file://ecr-policy.json

Azure (Azure Kubernetes Service)

Service Principal / Managed Identity: mcp-aks-sp

Required Azure RBAC Roles

RoleScopePurposeRequired For
Azure Kubernetes Service Cluster User RoleAKS ClusterAccess cluster credentialskubectl access
AcrPushContainer RegistryPush container imagesDocker build & push
AcrPullContainer RegistryPull container imagesDeployment
Contributor (limited scope)Resource GroupManage AKS resourcesDeployment updates
Monitoring Metrics PublisherSubscriptionPublish metricsObservability
Key Vault Secrets UserKey VaultAccess secretsRuntime config

Grant Commands (Azure CLI)

RESOURCE_GROUP="mcp-production-rg"
CLUSTER_NAME="mcp-production"
ACR_NAME="mcpcontainerregistry"
SUBSCRIPTION_ID=$(az account show --query id -o tsv)

# Create service principal
SP_INFO=$(az ad sp create-for-rbac \
  --name mcp-aks-sp \
  --role "Azure Kubernetes Service Cluster User Role" \
  --scopes /subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP)

SP_OBJECT_ID=$(echo $SP_INFO | jq -r '.appId')

# Grant ACR Push role
az role assignment create \
  --assignee $SP_OBJECT_ID \
  --role AcrPush \
  --scope /subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.ContainerRegistry/registries/$ACR_NAME

# Grant ACR Pull role
az role assignment create \
  --assignee $SP_OBJECT_ID \
  --role AcrPull \
  --scope /subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.ContainerRegistry/registries/$ACR_NAME

# Grant Contributor (scoped to resource group)
az role assignment create \
  --assignee $SP_OBJECT_ID \
  --role Contributor \
  --scope /subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP

# Grant Monitoring Metrics Publisher
az role assignment create \
  --assignee $SP_OBJECT_ID \
  --role "Monitoring Metrics Publisher" \
  --scope /subscriptions/$SUBSCRIPTION_ID

Workload Identity (Azure AD Pod Identity)

Pod Identity:
apiVersion: "aadpodidentity.k8s.io/v1"
kind: AzureIdentity
metadata:
  name: mcp-identity
  namespace: mcp-server-langgraph
spec:
  type: 0  # User-assigned managed identity
  resourceID: /subscriptions/SUBSCRIPTION_ID/resourcegroups/RESOURCE_GROUP/providers/Microsoft.ManagedIdentity/userAssignedIdentities/mcp-identity
  clientID: CLIENT_ID
Pod Identity Binding:
apiVersion: "aadpodidentity.k8s.io/v1"
kind: AzureIdentityBinding
metadata:
  name: mcp-identity-binding
  namespace: mcp-server-langgraph
spec:
  azureIdentity: mcp-identity
  selector: mcp-server-langgraph

Kubernetes RBAC (Common to All Platforms)

Namespace-Level Permissions

ServiceAccount

apiVersion: v1
kind: ServiceAccount
metadata:
  name: mcp-server-langgraph
  namespace: mcp-server-langgraph

Role

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: mcp-server-langgraph
  namespace: mcp-server-langgraph
rules:
  # Allow reading ConfigMaps
  - apiGroups: [""]
    resources: ["configmaps"]
    verbs: ["get", "list", "watch"]

  # Allow reading Secrets
  - apiGroups: [""]
    resources: ["secrets"]
    verbs: ["get", "list"]

  # Allow reading Services
  - apiGroups: [""]
    resources: ["services"]
    verbs: ["get", "list"]

  # Allow creating Events
  - apiGroups: [""]
    resources: ["events"]
    verbs: ["create", "patch"]

RoleBinding

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: mcp-server-langgraph
  namespace: mcp-server-langgraph
subjects:
  - kind: ServiceAccount
    name: mcp-server-langgraph
    namespace: mcp-server-langgraph
roleRef:
  kind: Role
  name: mcp-server-langgraph
  apiGroup: rbac.authorization.k8s.io

CI/CD Service Account Permissions

GitHub Actions (All Platforms)

Required Permissions:
  1. Pull from source repository - GitHub token (automatic)
  2. Authenticate to cloud provider - Workload Identity Federation / OIDC
  3. Push container images - Container registry write access
  4. Deploy to Kubernetes - Cluster access with deployment permissions

Deployment Pipeline Permissions

# GitHub Actions workflow permissions
permissions:
  contents: read        # Read repository contents
  id-token: write       # Request OIDC tokens for cloud auth
  packages: write       # Push to GitHub Container Registry (optional)
  deployments: write    # Create deployment statuses

Validation Scripts

GCP Validation

#!/bin/bash
# validate-gcp-permissions.sh

SERVICE_ACCOUNT="mcp-staging-sa@PROJECT_ID.iam.gserviceaccount.com"

REQUIRED_ROLES=(
  "roles/artifactregistry.writer"
  "roles/container.developer"
  "roles/logging.logWriter"
  "roles/monitoring.metricWriter"
  "roles/secretmanager.secretAccessor"
)

echo "Validating GCP IAM roles..."
GRANTED_ROLES=$(gcloud projects get-iam-policy $PROJECT_ID \
  --flatten="bindings[].members" \
  --filter="bindings.members:${SERVICE_ACCOUNT}" \
  --format="value(bindings.role)")

for role in "${REQUIRED_ROLES[@]}"; do
  if echo "$GRANTED_ROLES" | grep -q "$role"; then
    echo "✓ $role"
  else
    echo "✗ $role (MISSING)"
    exit 1
  fi
done

echo "✓ All required IAM roles present"

AWS Validation

#!/bin/bash
# validate-aws-permissions.sh

ROLE_NAME="mcp-eks-deployment-role"

echo "Validating AWS IAM policies..."
aws iam list-attached-role-policies --role-name $ROLE_NAME
aws iam list-role-policies --role-name $ROLE_NAME

echo "✓ IAM policies validated"

Azure Validation

#!/bin/bash
# validate-azure-permissions.sh

SP_OBJECT_ID="your-service-principal-id"
RESOURCE_GROUP="mcp-production-rg"

echo "Validating Azure RBAC roles..."
az role assignment list --assignee $SP_OBJECT_ID --resource-group $RESOURCE_GROUP

echo "✓ RBAC roles validated"

Troubleshooting

Common Permission Errors

GCP: “Permission denied on Artifact Registry”

Error:
denied: Permission "artifactregistry.repositories.uploadArtifacts" denied
Fix:
gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:${SERVICE_ACCOUNT}" \
  --role="roles/artifactregistry.writer"

AWS: “AccessDenied ECR”

Error:
denied: User: arn:aws:sts::ACCOUNT:assumed-role/... is not authorized to perform: ecr:PutImage
Fix: Apply ECR custom policy (see above)

Azure: “Authorization failed for ACR”

Error:
unauthorized: authentication required
Fix:
az role assignment create \
  --assignee $SP_OBJECT_ID \
  --role AcrPush \
  --scope /subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.ContainerRegistry/registries/$ACR_NAME

Security Best Practices

1. Use Workload Identity / IRSA

  • Do: Use platform-native workload identity (GCP Workload Identity, AWS IRSA, Azure Pod Identity)
  • Don’t: Use long-lived service account keys

2. Principle of Least Privilege

  • Do: Grant only required permissions
  • Don’t: Grant Owner, Editor, or Admin roles

3. Scope Permissions Narrowly

  • Do: Scope to specific resources (namespace, resource group, etc.)
  • Don’t: Grant organization-wide or subscription-wide permissions

4. Regular Audits

  • Do: Regularly review and audit permissions
  • Don’t: Set-and-forget permissions

5. Use Resource-Level Permissions

  • Do: Grant access to specific container registries, clusters
  • Don’t: Grant wildcard (*) resource access

References

Documentation

  • GCP: GCP Configuration Guide
  • AWS: AWS EKS Configuration (see scripts and Terraform modules below)
  • Azure: Azure AKS Configuration (see scripts and Terraform modules below)
AWS EKS and Azure AKS deployment documentation is available via deployment scripts and Terraform modules. Dedicated configuration guides are planned for future releases.

Scripts

  • GCP Setup: scripts/gcp/setup-staging-infrastructure.sh
  • AWS Setup: scripts/deploy-aws-eks.sh
  • Azure Setup: scripts/deploy-azure-aks.sh

Terraform Modules

  • GCP: terraform/modules/gke/
  • AWS: terraform/modules/eks/
  • Azure: terraform/modules/aks/

Maintained By: DevOps Team Last Reviewed: 2025-11-02 Next Review: 2025-12-01