# 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 ![image](https://hackmd.io/_uploads/S1wsX_zkkx.png) # 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 ![image](https://hackmd.io/_uploads/r144r_GJJl.png) 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" ] }, ] ```