Understanding Role Based Access Control (RBAC) with Amazon EKS – Part 2

This is the latest installment of a multi-part series covering RBAC with Amazon EKS, Joe Keegan, BlueChipTek Lead Cloud Services explains how AWS IAM integrates with Kubernetes. In part 1, he covered Kubernetes roles and how to assign those role to IAM principals. That part covers how IAM integrated with Kubernetes for authorization. In this part he’ll cover how IAM integrates with kubectl for authentication of IAM principals. The final part will show how to put it all together to allow multiple teams to coexist on the same cluster without risk of them interfering with each other

aws-iam-authenticator

The aws-iam-authentication utility is used to integrate Kubernetes authentication with IAM and is needed to interact with an EKS cluster. Anytime you use kubectl to perform an action on the EKS cluster the aws-iam-authenticator is used to generate an STS token. That STS token is used to authenticate the client when making API calls.

The aws-iam-authenticator also runs as server mode on the EKS API Server. When the EKS API Server receives the API call it uses the aws-iam-authentication to verify that the token is valid and the IAM principal that created the token. This process is depicted below.

STS-diagram.png#asset:3357


Once the EKS API Server knows the IAM principal who sent the API call it can then use the mappings defined in the aws-auth ConfigMap to see which Kubernetes groups the principal is part of. This is discussed in part 1 of this series.

You can generate tokens with the aws-iam-authentication tool by running it from the command line. You can see that each time you run it generates a new token. The ‘-i eks-cluster’ tells the aws-iam-authentication tool that the cluster id is “eks-cluster”.

$ aws-iam-authenticator token -i eks-cluster
{"kind":"ExecCredential","apiVersion":"client.authentication.k8s.io/v1alpha1","spec":{},"status":{"token":"k8s-aws-v1.aHR0cHM6Ly9zdHMuYW1hem9uYXdzLmNvbS8_QWN0aW9uPUdldENhbGxlcklkZW50aXR5JlZlcnNpb249MjAxMS0wNi0xNSZYLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFTSUE1REFPVzdFM0lSSkJDU0NKJTJGMjAxODA5MjclMkZ1cy1lYXN0LTElMkZzdHMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDE4MDkyN1QxOTM1NTRaJlgtQW16LUV4cGlyZXM9NjAmWC1BbXotU2VjdXJpdHktVG9rZW49RlFvR1pYSXZZWGR6RUgwYUREaUZ2R3VSeGglMkZUdDN4UVlDTDNBVHI4R01TbCUyRlZLN2ozbE1sJTJCZ3EyTk5tcjRzUnprakRTdiUyRmFweTlUclB6ODRmbENrMERLVHZ1a1ZoMko3WkNJNk1LWDkydW0zQ2p1OUhGcUp3VFRSTTdXJTJGak1OUENLWjJDWTd3ejFtdWFjaERNJTJGREVnZmladFdxYzA3Vjc0JTJCRGhFJTJCN0kyTVMxVmprQ3NEWEtxWWM5S3JkajFPbTRFc2o1S3lYRVk4ZHpzRG03S2FNcGh4ZUdKaU94VGYxR0M2WTklMkZLMWZubkElMkIySG51UnJBT3I0M0w3SjNHb3hYaHU1NEVtcEM2T2dmZUVKRjQlMkJjSjVXbnFVdnZ4cSUyQjBLTUc5MlJYNGN3NU1RRVFTV2l6SElpc3pHTTF2RUtYaTRmM2VxVjlheTBtT250cnQ1V3V4S3dmSkMwT0ZWRmcxeDBkQXBXekYxaFVwU3h1MG9tdUswM1FVJTNEJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCUzQngtazhzLWF3cy1pZCZYLUFtei1TaWduYXR1cmU9YjE4NWZhMjdhMDg1NmE4MzZkOTk3MWJkZWVkMzgxNTFjODk0YTdjNTM0NWVmODcyMDU0YmUwZTYzMzM3YzM0Ng"}}
$ aws-iam-authenticator token -i eks-cluster
{"kind":"ExecCredential","apiVersion":"client.authentication.k8s.io/v1alpha1","spec":{},"status":{"token":"k8s-aws-v1.aHR0cHM6Ly9zdHMuYW1hem9uYXdzLmNvbS8_QWN0aW9uPUdldENhbGxlcklkZW50aXR5JlZlcnNpb249MjAxMS0wNi0xNSZYLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFTSUE1REFPVzdFM0pXVEg1R1dKJTJGMjAxODA5MjclMkZ1cy1lYXN0LTElMkZzdHMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDE4MDkyN1QxOTM1NTZaJlgtQW16LUV4cGlyZXM9NjAmWC1BbXotU2VjdXJpdHktVG9rZW49RlFvR1pYSXZZWGR6RUgwYURKTVNaaGl2eW4lMkJFa1NMdDl5TDNBVEN3M0kxWWxmYXBEVzFJVCUyQjdpTFhZUk1sS0JRaFJwOHF5MHl3OFdYTDJzanZOQlBrMWZReVloWEpmTTV0anVFdmE4YXQ0V3RjTUhSNUFWaU04aWlmZHolMkYlMkZiMHEzOGdaOHIwVVdZdVF6eW5LWWE4VllzVWdBQWxUdHJVRFJVcEx6TCUyRkFDcFd1VUVxRVRDTXg5eEZoV3ByaUNPdjJteFklMkYxcmNERVJRcnRaeEE4T0RmMDh3SjBESXJZcjVsaWo1Q0dDbzcwdVhLQ3g2YzZHZUQyQkhyVTkwamMzQ2tGaERyQjVVYklEY2w3JTJGM1VDWFdPTXdIb1Rzbk9qUGdWTlVCcWVsJTJCb3VrelRRS2kybEZMTkp0R1dHZEtPcDQ3dXU0QVJyYVRIVk9jeEdzTGU1VWJFdjFpTXcwelVhbDYyNmZlTzFNWG5sTVBWekFvbmVLMDNRVSUzRCZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QlM0J4LWs4cy1hd3MtaWQmWC1BbXotU2lnbmF0dXJlPTVhMTAyMDcxYzBlZmRmOTUxMTQ5ZDEwZTdmN2ZhZGZlMjg4MTc4ZGFmZjA1Mjc2ODliYjU0YzhhYzI1NTVmZDU"}}

By default, the IAM principal used to generate the STS token is based on the AWS credentials profile you have configured, in the same manner as when you are using the AWS CLI. This will either be the default profile, or the profile set in the AWS_DEFAULT_PROFILE environment variable.

Alternatively, you can specify an ARN of the role you wish to assume to generate the STS token. This is done with a ‘-r’ argument like so.

$ aws-iam-authenticator token -i eks-cluster -r arn:aws:iam::123456789012:role/eks-team1-admins 

kubectl integration

When setting up your EKS cluster you likely generate use ‘aws eks update-kubeconfig` command to generate the kubeconfig needed to connect to your cluster. The section relevant to the aws-iam-authenticator is the users section of the config. By default, it looks something like:

users:
- name: arn:aws:eks:us-west-2:123456789012:cluster/eks-cluster
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1alpha1
      args:
      - token
      - -i
      - eks-cluster
      command: aws-iam-authenticator

This tells kubectl that when the context is set to use the user “arn:aws:eks:us-west-2:123456789012:cluster/eks-cluster” then the following command to generate the STS token “aws-iam-authenticator token -i eks-cluster” is run prior to sending the API call to the EKS cluster.

I find using kubectl with an EKS cluster to be a bit more sluggish than with a vanilla Kubernetes cluster and it’s because there is a call to STS for each call kubectl command. You can create other users in your kubeconfig file and utilize the “-r” argument to specify different IAM roles to use, which in turn will map to different Kubernetes groups. The following kubeconfig defines 3 users and 3 contexts for our EKS cluster. One user and context for the cluster-admin using the IAM role used to setup the cluster. The other two users and contexts are for specific teams that are given admin to their respective namespaces.

apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: <SNIP>
    server: https://address.sk1.us-west-2.eks.amazonaws.com
  name: arn:aws:eks:us-west-2:123456789012:cluster/eks-cluster
contexts:
- name: cluster-admins
  context:
    cluster: arn:aws:eks:us-west-2:123456789012:cluster/eks-cluster
    user: arn:aws:eks:us-west-2:123456789012:cluster/eks-cluster
- name: team1-admins
  context:
    cluster: arn:aws:eks:us-west-2:123456789012:cluster/eks-cluster
    user: team1-admins
    namespace: team1
- name: team2-admins
  context:
    cluster: arn:aws:eks:us-west-2:123456789012:cluster/eks-cluster
    user: team2-admins
    namespace: team2
current-context: cluster-admins
kind: Config
preferences: {}
users:
- name: arn:aws:eks:us-west-2:123456789012:cluster/eks-cluster
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1alpha1
      args:
      - token
      - -i
      - eks-cluster
      - -r
      - arn:aws:iam::123456789012:role/eks-cluster-admins
      command: aws-iam-authenticator
- name: team1-admins
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1alpha1
      args:
      - token
      - -i
      - eks-cluster
      - -r
      - arn:aws:iam::123456789012:role/eks-team1-admins
      command: aws-iam-authenticator
- name: team2-admins
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1alpha1
      args:
      - token
      - -i
      - eks-cluster
      - -r
      - arn:aws:iam::123456789012:role/eks-team2-admins
      command: aws-iam-authenticator

The next installment of the series shows the full implementation of the two teams and how to grant them access to their respective namespaces.

If you find that you’d like to help talking these kinds of problems with EKS then checkout out Jumpstart for Container Orchestration. We can come on site and show you how to get EKS up and running securely and ready for production.