# Kubernetes RBAC with AWS IAM integration
# Overview
This documentation provides a comprehensive guide on implementing Role-Based Access Control (RBAC) in a Kubernetes environment seamlessly integrated with AWS Identity and Access Management (IAM). This integration allows organizations to leverage our existing AWS IAM infrastructure to manage and control access to Kubernetes resources.
This RBAC module is implemented by Terraform and can be found at: <**github_placeholder**>
## **Terminologies**
**RBAC** is a security mechanism that controls access to resources within a cluster. It allows you to define **who** (users or groups) can do **what** (verbs) on **which** resources (nouns).
- **Roles and RoleBindings:**
- **Role:** set of permissions defined for a specific **namespace**. It specifies **what** actions (verbs) are allowed on **which** resources (nouns) **within** that **namespace**. For example, a role might grant read access to pods in a namespace.
- **RoleBinding:** A role binding binds a **role** to a **user**, a **group**, or a **service account** within a specific **namespace**. It establishes the connection between the role and the entity (user, group, or service account) that should have the defined permissions.
- **ClusterRoles and ClusterRoleBindings:**
- **ClusterRole:** Similar to a role, but it works across **all namespaces** in a cluster. It defines permissions for **cluster-level** resources, like nodes and persistent volumes.
- **ClusterRoleBinding:** Binds a cluster role to a **user**, **group**, or **service account** across the **entire cluster**. It allows users or service accounts to have specific roles across all namespaces

# Example
The below code snippet describes how the module is defined and mapping with existing AWS IAM roles
```java
module "k8s-rbac" {
source = "../../modules/eks/eks-rbac"
depends_on = [module.eks]
cluster_roles = [
{
name = "admin"
privilege = "admin"
trusted_role_arn = [
local.administrator_role_arn
]
},
{
name = "developer"
privilege = "developer"
trusted_role_arn = [
local.developer_role_arn
]
}
]
namespace_roles = [
{
namespace = "service-A"
privilege = "readonly"
trusted_role_arn = [
local.service_A_readonly_role_arn
]
},
{
namespace = "service-B"
privilege = "developer"
trusted_role_arn = [
local.service_B_developer_role_arn
]
}
]
profile_roles = [
{
role_arn = module.eks.aws_iam_role-node.arn
profile_type = "node"
privilege = "node"
name = "node"
},
{
role_arn = module.eks.eks_default_auth_role_arn
profile_type = "custom"
privilege = "admin"
name = "master-role"
},
{
role_arn = local.jenkins_oidc_role
profile_type = "custom"
privilege = "admin"
name = "jenkins"
},
{
role_arn = module.eks.fargate_profile.fargate_profile_pod_execution_role_arn
profile_type = "fargate"
privilege = "fargate"
name = "fargate"
},
{
role_arn = local.github_terraform_ops_role_arn
profile_type = "custom"
privilege = "admin"
name = "github"
}
]
aws_auth_users = []
tags = {
environment = local.environment
}
}
```
# How it works
## **Cluster roles and namespace roles**
Under the hood, this Terraform code **creates** the resources below
- An IAM role that **trust** the role arns in `trusted_role_arn` to assume it with `sts:AssumeRole`
- IAM roles for cluster: `eks-admin-clusterrole` and `eks-developer-clusterrole`
- IAM roles for namespace: `eks-service-A-readonly-namespace-role` and `eks-service-B-developer-namespace-role`
- **ClusterRole** and **ClusterRoleBindings** for `cluster_roles` array
- **Role** and **RoleBinding** for `namespace_roles` array
These **ClusterRoleBindings** and **RoleBindings** then will be linked to AWS IAM through `aws-auth` configmap inside `kube-system` namespace as the documentation above described
```java
- rolearn: arn:aws:iam::<account-id>:role/eks-admin-clusterrole
username: admin
groups:
- custom:admin-group # clusterrolebinding
- rolearn: arn:aws:iam::<account-id>:role/eks-developer-clusterrole
username: developer
groups:
- custom:developer-group # clusterrolebinding
- rolearn:
arn:aws:iam::<account-id>:role/eks-service-A-readonly-namespace-role
username: service-A-readonly
groups:
- custom:service-A-readonly-group # rolebinding
- rolearn:
arn:aws:iam::<account-id>:role/eks-service-B-developer-namespace-role
username: service-B-developer
groups:
- custom:service-B-developer-group # rolebinding
```
### **How does the trusted role work?**
As you can see from the previous sections, we specify which **IAM** roles are trusted by the newly created **IAM** roles through `trusted_role_arns` variable
It would look like this on the console, here, the **Administrator SSO** role are trusted to perform `sts:AssumeRole` action https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html

If the user has permission to use this SSO role through logging in by SSO, he/she will have the permission to assume the `eks-admin-clusterrole` and perform actions inside the Kubernetes Cluster
## **Profile roles**
While `cluster_roles` and `namespace_roles` **creates** new IAM roles with associated Kubernetes permission, the `profile_roles` field is for specifying **existing** IAM roles on AWS IAM, that we need to map them into the Kubernetes cluster with special permission
The result `aws-auth` configmap will contain these data for these IAM roles
```java
- rolearn: arn:aws:iam::<account_id>:role/eks-node-cluster
username: system:node:{{EC2PrivateDNSName}}
groups:
- system:bootstrappers # permission for managed nodes
- system:nodes
- rolearn: arn:aws:iam::<account_id>:role/eks-auth-role
username: master-role
groups:
- system:masters # admin
- rolearn: arn:aws:iam::<account_id>:role/jenkins-oidc-role
username: jenkins
groups:
- system:masters # admin
- rolearn:
arn:aws:iam::<account_id>:role/eks-dev-fargate-profile-2023112103250071030000000a
username: system:node:{{SessionName}}
groups:
- system:bootstrappers # permission for fargate
- system:nodes
- system:node-proxier
- rolearn: arn:aws:iam::<account_id>:role/github-actions/role-terraform-ops
username: github
groups:
- system:masters # admin
```
# Organizing RBAC with AWS SSO
## **Strategy**
We could organize the access permission to Kubernetes cluster by **mapping** the SSO roles to the cluster roles and namespaces role
The table below describes a good practice for this mapping
| **EKS roles** | | **AWS SSO Roles** |
| --- | --- | --- |
| Cluster role | eks-admin-clusterrole | AdministratorAccess |
| | eks-developer-clusterrole | KubernetesDevs |
| | eks-viewer-clusterrole | BackendDevs |
| Namespace role | eks-service-B-admin-namespace-role | ServiceBAdmin |
| | eks-service-B-admin-namespace-role | ServiceBDevs |
The table above can be translated to the Terraform code with similar configuration
```java
cluster_roles = [
{
name = "admin"
privilege = "admin"
trusted_role_arn = [
"arn:aws:iam::<account_id>:role/aws-reserved/sso.amazonaws.com/us-west-2/AdministratorAccess"
]
},
{
name = "developer"
privilege = "developer"
trusted_role_arn = [
"arn:aws:iam::<account_id>:role/aws-reserved/sso.amazonaws.com/us-west-2/KubernetesDevs"
]
},
{
name = "viewer"
privilege = "readonly"
trusted_role_arn = [
"arn:aws:iam::<account_id>:role/aws-reserved/sso.amazonaws.com/us-west-2/BackendDevs"
]
}
]
namespace_roles = [
{
namespace = "service-B"
privilege = "admin"
trusted_role_arn = [
"arn:aws:iam::<account_id>:role/aws-reserved/sso.amazonaws.com/us-west-2/ServiceBAdmin"
]
},
{
namespace = "service-B"
privilege = "developer"
trusted_role_arn = [
"arn:aws:iam::<account_id>:role/aws-reserved/sso.amazonaws.com/us-west-2/ServiceBDevs"
]
},
]
```