Fixing Permission Denied Deployments to EKS from GitLab CI/CD with IRSA
- Get link
- X
- Other Apps
Fixing Permission Denied Deployments to EKS from GitLab CI/CD with IRSA: A Comprehensive Guide
As a Senior Cloud Solution Architect and Software Engineer, I frequently encounter challenges related to secure and efficient deployments in cloud-native environments. One common hurdle is the "Permission Denied" error during deployments to Amazon EKS clusters orchestrated by GitLab CI/CD pipelines, especially when leveraging IAM Roles for Service Accounts (IRSA). This guide provides a deep dive into diagnosing, troubleshooting, and resolving such issues, ensuring your CI/CD pipelines run smoothly and securely.
Understanding IRSA and GitLab CI/CD Integration
IAM Roles for Service Accounts (IRSA) is a critical AWS feature that allows Kubernetes service accounts to assume IAM roles. This provides fine-grained, secure access to AWS services from pods running within your EKS cluster, eliminating the need for long-lived AWS credentials. When integrating with GitLab CI/CD, your pipeline typically uses a Kubernetes context to interact with the EKS cluster, often configured to use a specific service account that, in turn, is associated with an IAM role via IRSA.
How it Works (Simplified)
- GitLab CI/CD Runner: Deploys
kubectlcommands to the EKS cluster. - Kubernetes Service Account: The runner authenticates with EKS using a Kubeconfig that points to a specific Kubernetes Service Account (SA).
- IRSA Association: This SA is annotated with an AWS IAM Role ARN (
eks.amazonaws.com/role-arn). - AWS STS: When a pod (or in this case, the context for the CI/CD runner interacting with the cluster) uses this SA, AWS STS exchanges the Kubernetes token for temporary AWS credentials from the associated IAM Role.
- AWS API Calls: These temporary credentials are then used to make API calls to AWS services (e.g., managing EC2 instances, S3 buckets, or in this context, EKS itself for deploying resources).
Symptom Analysis & Root Causes
"Permission Denied" errors manifest in various ways, often indicating that the IAM role associated with your EKS service account lacks the necessary permissions to perform specific actions on Kubernetes resources or AWS services.
Common Symptoms
Error from server (Forbidden): deployments.apps "my-app" is forbidden: User "arn:aws:iam::xxxxxxxxxxxx:user/i-am-role-name" cannot create/get/update deployments.apps in namespace "my-namespace"kubectl apply -f my-manifest.yamlfails with permission errors.- Pipeline logs show errors like
User: arn:aws:sts::xxxxxxxxxxxx:assumed-role/MyGitLabIRSARole/i-xxxxxxxxxxxx is not authorized to perform: eks:DescribeCluster on resource: arn:aws:eks:REGION:ACCOUNT_ID:cluster/my-cluster - Helm deployments failing with similar authorization errors.
Typical Root Causes
- Incorrect IAM Role Permissions: The most common issue. The IAM role linked to your Kubernetes service account does not have the necessary AWS IAM policies attached to allow actions on EKS or other AWS resources.
- Missing Kubernetes RBAC Permissions: Even if the IAM role is correct, the Kubernetes Service Account itself might not have the necessary Role-based Access Control (RBAC) permissions (Roles and RoleBindings) within the EKS cluster to create, update, or delete Kubernetes resources.
- IAM Role Trust Policy Misconfiguration: The trust policy of the IAM role might not allow the EKS OIDC provider to assume the role. This prevents IRSA from working entirely.
- Service Account Annotation Errors: The Kubernetes service account might not be correctly annotated with the
eks.amazonaws.com/role-arnpointing to the correct IAM role. - OIDC Provider Not Configured or Mismatched: The EKS cluster's OIDC Identity Provider (IdP) might not be created or its ARN might not match in the IAM role's trust policy.
- Kubeconfig Context Issues: The GitLab CI/CD runner's kubeconfig might not be pointing to the correct cluster, context, or user (service account).
- Namespace Mismatch: Trying to deploy to a namespace where the service account lacks permissions, or the service account itself exists in a different namespace than intended.
- AWS STS Throttling: Less common, but possible with very high request volumes, leading to temporary credential acquisition failures.
Step-by-Step Resolution Guide
Follow these steps to systematically diagnose and resolve "Permission Denied" errors for EKS deployments from GitLab CI/CD using IRSA.
Step 1: Verify EKS OIDC Identity Provider Configuration
Ensure your EKS cluster has an OIDC Identity Provider configured and that it's accessible. This is fundamental for IRSA to function.
This command should return the OIDC issuer URL. If not, you need to create one:
Step 2: Inspect the Kubernetes Service Account
Check if the Kubernetes Service Account (SA) used by your GitLab CI/CD pipeline is correctly annotated with the IAM Role ARN.
Look for the eks.amazonaws.com/role-arn annotation. It should point to the full ARN of the IAM role.
If the annotation is missing or incorrect, update your service account manifest and re-apply:
Step 3: Review IAM Role Trust Policy
The IAM role must trust the EKS OIDC provider to allow assuming the role.
The output should contain a trust policy similar to this, replacing OIDC_ISSUER_URL and AWS_ACCOUNT_ID with your specific values:
Key elements to check:
"Federated": "arn:aws:iam::ACCOUNT_ID:oidc-provider/OIDC_ISSUER_URL"- Must match your EKS OIDC provider."OIDC_ISSUER_URL:sub": "system:serviceaccount:your-namespace:your-service-account-name"- Thesubclaim must precisely match your service account and namespace.
If incorrect, update the trust policy using the AWS CLI or console.
Step 4: Validate IAM Role Permissions (Managed Policies & Inline Policies)
Ensure the IAM role has the necessary permissions to interact with EKS and deploy resources. This is where most "Permission Denied" issues originate.
Identify the specific actions that are failing from your pipeline logs. For example, if it's failing to create deployments, it needs appropriate Kubernetes API permissions.
Examine each policy. Common permissions required for deployments include:
AmazonEKSClusterPolicy(Managed Policy) for basic EKS cluster interaction.- Custom policies allowing actions like:
"eks:DescribeCluster""ecr:GetAuthorizationToken","ecr:BatchCheckLayerAvailability","ecr:GetDownloadUrlForLayer","ecr:BatchGetImage"(for pulling images from ECR).- Specific Kubernetes API actions depending on what your application deploys (e.g.,
"kubernetes:CreatePod","kubernetes:GetDeployment","kubernetes:UpdateService"). For general deployment, consider specific actions rather than broad"kubernetes:*".
Update the IAM role policies to grant the missing permissions. Always follow the principle of least privilege.
Step 5: Verify Kubernetes RBAC Permissions (Roles & RoleBindings)
Even with correct IRSA configuration, the Kubernetes Service Account itself needs appropriate RBAC permissions within the cluster.
Check the Role and RoleBinding associated with your Service Account in the target namespace.
Example of a Role and RoleBinding for a deployer Service Account:
Ensure the Role grants the necessary verbs on the correct resources in the target apiGroups, and that the RoleBinding links this Role to your ServiceAccount.
Step 6: Debugging in GitLab CI/CD
If all configurations seem correct, enable verbose logging in your GitLab CI/CD pipeline steps that interact with EKS.
- Add
--v=6or--v=8tokubectlcommands to get detailed output. - Ensure environment variables like
KUBECONFIGare correctly set within your CI/CD job. - Temporarily try to explicitly set AWS credentials in a test job (for debugging only, do not use in production) to rule out IRSA specific issues vs. general IAM permission issues.
Best Practices for Prevention & Performance Optimization
Adopting these best practices will minimize permission-related issues and enhance the security and efficiency of your EKS deployments.
- Least Privilege Principle: Always grant the minimum necessary permissions to your IAM roles and Kubernetes service accounts. Regularly review and audit these permissions.
- Automate IRSA Configuration: Use tools like
eksctlor Terraform/CloudFormation to provision and manage your EKS OIDC provider, IAM roles, and service account associations. This reduces manual errors and ensures consistency. - Dedicated Service Accounts: Create specific Kubernetes Service Accounts for each application or deployment pipeline, rather than using a general-purpose SA. Each SA should ideally have its own IRSA-linked IAM role.
- Namespace-Scoped RBAC: Define Kubernetes Roles and RoleBindings at the namespace level where possible, rather than using ClusterRoles. This limits the blast radius of any permission misconfiguration to a single namespace.
- Version Control All Configurations: Store all your Kubernetes manifests (Service Accounts, Roles, RoleBindings) and infrastructure-as-code (IAM roles, OIDC providers) in Git. This allows for change tracking, peer review, and easy rollbacks.
- Regular Audits: Periodically audit your IAM policies and Kubernetes RBAC configurations to identify overly permissive settings or stale permissions that are no longer needed.
- Centralized Logging and Monitoring: Ensure comprehensive logging from your EKS cluster (CloudWatch Logs, Kubernetes audit logs) and GitLab CI/CD pipelines. Integrate with monitoring tools to quickly identify and alert on deployment failures and permission issues.
- GitLab CI/CD Variables for Secrets: Store sensitive information like AWS region, cluster names, and Kubeconfig details as protected GitLab CI/CD variables, not directly in your
.gitlab-ci.yml, for enhanced security.
Frequently Asked Questions
Q1: How can I test IAM role permissions without running the entire GitLab CI/CD pipeline?
A1: You can temporarily configure your local kubectl to use the EKS service account and its associated IAM role. First, get the token for the service account:
Then, use a tool like aws-iam-authenticator or directly modify your kubeconfig to use this token for a specific user/context, and then attempt the failing kubectl commands. Alternatively, for just verifying the IAM role itself (without Kubernetes RBAC), you can use aws sts assume-role-with-web-identity with a dummy token in a local script and then execute AWS CLI commands with the returned temporary credentials.
Q2: My deployments worked before, but now they are failing with "Permission Denied". What changed?
A2: This often indicates a recent change to one of the permission-related components. Common culprits include:
- IAM Policy Updates: Someone might have modified or detached a policy from your IAM role.
- Kubernetes RBAC Changes: A Role or RoleBinding might have been updated or deleted.
- EKS Cluster Upgrade: EKS upgrades can sometimes require adjustments to OIDC or IAM configurations, though this is less common directly for IRSA unless the OIDC provider URL changes.
- Service Account Manifest Changes: The
eks.amazonaws.com/role-arnannotation might have been accidentally removed or altered. - Application Requirements: The application you're deploying might now require new permissions (e.g., access to a new AWS service or a new Kubernetes resource type) that haven't been granted.
Review recent changes in your version control system for all related configurations (IAM, Kubernetes manifests, CI/CD pipeline definitions).
Q3: Can I use a single IAM role for multiple service accounts?
A3: Yes, you can. The IAM role's trust policy can be configured to allow multiple service accounts to assume it by using a wildcard or listing multiple StringEquals conditions for the "OIDC_ISSUER_URL:sub" claim (e.g., "OIDC_ISSUER_URL:sub": ["system:serviceaccount:ns1:sa1", "system:serviceaccount:ns2:sa2"]). However, for enhanced security and adherence to the principle of least privilege, it's generally recommended to use dedicated IAM roles for dedicated service accounts, especially across different applications or security boundaries. This approach makes auditing, troubleshooting, and revoking permissions much easier and more granular.
- Get link
- X
- Other Apps