15

I'm using Amazon EKS for Kubernetes deployment (initially created by an AWS admin user), and currently having difficulty to use the AWS credentials from AWS STS assume-role to execute kubectl commands to interact with the stack

I have 2 EKS stacks on 2 different AWS accounts (PROD & NONPROD), and I'm trying to get the CI/CD tool to deploy to both kubernetes stacks with the credentials provided by AWS STS assume-role but I'm constantly getting error such as error: You must be logged in to the server (the server has asked for the client to provide credentials).

I have followed the following link to add additional AWS IAM role to the config:

But I'm not sure what I'm not doing right.

I ran "aws eks update-kubeconfig" to update the local .kube/config file, contents populated as below:

apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: [hidden]
    server: https://[hidden].eu-west-1.eks.amazonaws.com
  name: arn:aws:eks:eu-west-1:[hidden]:cluster/demo-eks
contexts:
- context:
    cluster: arn:aws:eks:eu-west-1:[hidden]:cluster/demo-eks
    user: arn:aws:eks:eu-west-1:[hidden]:cluster/demo-eks
  name: arn:aws:eks:eu-west-1:[hidden]:cluster/demo-eks
current-context: arn:aws:eks:eu-west-1:[hidden]:cluster/demo-eks
kind: Config
preferences: {}
users:
- name: arn:aws:eks:eu-west-1:[hidden]:cluster/demo-eks
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1alpha1
      args:
      - token
      - -i
      - triage-eks
      command: aws-iam-authenticator

and had previously updated Kubernetes aws-auth ConfigMap with an additional role as below:

data:
  mapRoles: |
    - rolearn: arn:aws:iam::[hidden]:role/ci_deployer
      username: system:node:{{EC2PrivateDNSName}}
      groups:
        - system:masters

My CI/CD EC2 instance can assume the ci_deployer role for either AWS accounts.

Expected: I can call "kubectl version" to see both Client and Server versions

Actual: but I get "the server has asked for the client to provide credentials"

What is still missing?

After further testing, I can confirm kubectl will only work from an environment (e.g. my CI EC2 instance with an AWS instance role) of the same AWS account where the EKS stack is created. This means that my CI instance from account A will not be able to communicate with EKS from account B, even if the CI instance can assume a role from account B, and the account B role is included in the aws-auth of the kube config of account B EKS. I hope its due to missing configuration as I find this rather undesirable if a CI tool can't deploy to multiple EKS's from multiple AWS accounts using role assumption.

Look forward to further @Kubernetes support on this

David Maze
  • 130,717
  • 29
  • 175
  • 215
Raymond Ng
  • 151
  • 1
  • 1
  • 4

2 Answers2

10

Can kubectl work from an assumed role from AWS

Yes, it can work. A good way to troubleshoot it is to run from the same command line where you are running kubectl:

$ aws sts get-caller-identity

You can see the Arn for the role (or user) and then make sure there's a trust relationship in IAM between that and the role that you specify here in your kubeconfig:

command: aws-iam-authenticator
args:
   - "token"
   - "-i"
   - "<cluster-name>"
   - "-r"
   - "<role-you-want-to-assume-arn>"

or with the newer option:

command: aws
args:
- eks
- get-token
- --cluster-name
- <cluster-name>
- --role
- <role-you-want-to-assume-arn>

Note that if you are using aws eks update-kubeconfig you can pass in the --role-arn flag to generate the above in your kubeconfig.

In your case, some things that you can look at:

  • The credential environment variables are not set in your CI?:

    AWS_ACCESS_KEY_ID
    AWS_SECRET_ACCESS_KEY
    
  • Your ~/.aws/credentials file is not populated correctly in your CI. With something like this:

    [default]
    aws_access_key_id = xxxx
    aws_secret_access_key = xxxx
    
  • Generally, the environment variables take precedence so it could be that you could have different credentials altogether in those environment variables too.

  • It could also be the AWS_PROFILE env variable or the AWS_PROFILE config in ~/.kube/config

    users:
    - name: aws
      user:
        exec:
          apiVersion: client.authentication.k8s.io/v1alpha1
          command: aws-iam-authenticator
          args:
            - "token"
            - "-i"
            - "<cluster-name>"
            - "-r"
            - "<role-arn>"
          env:
            - name: AWS_PROFILE <== is this value set
              value: "<aws-profile>"
    
  • Is the profile set correctly under ~/.aws/config?

c4urself
  • 4,207
  • 21
  • 32
Rico
  • 58,485
  • 12
  • 111
  • 141
  • Hi @Rico, thanks for your reply. there's no AWS environment variables set and the "aws sts get-caller-identity" shows the following json reply to confirm the correct role has been assumed. `{ "Account": [account_id], "UserId": "AROAJUXQNBLRYT5KPW5TG:test", "Arn": "arn:aws:sts::[account_id]:assumed-role/ci_deployer/test" }` Also I don't have AWS_PROFILE in .kube/config either. And I do believe its credentials related but just don't know what I've done wrong. Thanks – Raymond Ng Jan 19 '19 at 07:42
  • 1
    have a similar issue, ever figure this out? – c4urself Sep 12 '19 at 15:31
  • @c4urself what's the issue? You can post it on a different question – Rico Sep 12 '19 at 16:05
  • it's actually exactly the main question asked here, can `kubectl` work with assumed roles from instance-metadata on EC2... my `env:AWS_PROFILE` is set to `test` in kube-config, no access key or secret key set, ec2 instance which is allowed to assume a role ```[profile test] credential_source = Ec2InstanceMetadata region = us-east-1 role_arn = arn:aws:iam::123123123123:role/service/my-role-which-is-authed-in-configmap``` – c4urself Sep 12 '19 at 16:15
  • Added more details, yes, it can work, make sure that there's a trust relationship between the existing role and the role you want to assume in IAM. We use this on a daily basis. Let me know if you have any other questions. – Rico Sep 12 '19 at 16:44
2

From Step 1: Create Your Amazon Cluster

When an Amazon EKS cluster is created, the IAM entity (user or role) that creates the cluster is added to the Kubernetes RBAC authorization table as the administrator (with system:master permissions. Initially, only that IAM user can make calls to the Kubernetes API server using kubectl.

As you have discovered you can only access the cluster with the same user/role that created the EKS cluster in the first place.

There is a way to add additional roles to the cluster after creation by editing the aws-auth ConfigMap that has been created.

Add User Role

By editing the aws-auth ConfigMap you can add different levels of access based on the role of the user.

First you MUST have the "system:node:{{EC2PrivateDNSName}}" user

apiVersion: v1
kind: ConfigMap
metadata:
  name: aws-auth
  namespace: kube-system
data:
  mapRoles: |
    - rolearn: <ARN of instance role (not instance profile)>
      username: system:node:{{EC2PrivateDNSName}}
      groups:
        - system:bootstrappers
        - system:nodes

This is required for Kubernetes to even work, giving the nodes the ability to join the cluster. The "ARN of instance role" is the role that includes the required policies AmazonEKSWorkerNodePolicy, AmazonEKS_CNI_Policy, AmazonEC2ContainerRegistryReadOnly etc.

Below that add your role

   - rolearn: arn:aws:iam::[hidden]:role/ci_deployer
     username: ci-deployer
     groups:
       - system:masters

The 'username' can actually be set to about anything. It appears to only be important if there are custom roles and bindings added to your EKS cluster.

Also, use the command 'aws sts get-caller-identity' to validate the environment/shell and the AWS credentials are properly configured. When correctly configured 'get-caller-identity' should return the same role ARN specified in aws-auth.

grbonk
  • 609
  • 6
  • 22
  • 1
    Hi @grbonk, thanks for your reply. I agree with everything you said on how to add additional role to an existing aws-auth configuration, and I got it working last week too. But my problem was that there seems to be problem executing kubectl commands after assuming the role successfully from a different AWS account. I have appended some "further testing" finding (the last 2 paragraphs) to my original question to demonstrate the problem I experienced involving 2 different AWS accounts. Hope this helps in explaining more of my problem. Thanks for your time. – Raymond Ng Jan 23 '19 at 09:52
  • I sounds like then you will want to try doing something like this... I have not tried it yet though. https://docs.aws.amazon.com/IAM/latest/UserGuide/tutorial_cross-account-with-roles.html – grbonk Jan 25 '19 at 14:08
  • 1
    thanks for the comment, I am aware of the role assumption setup over multiple accounts, but the problem is kubectl with aws-iam-authenticator don't seem to work the way that we would expect using role assumption. I have raised this with AWS support and hopefully we will get to the bottom of this soon – Raymond Ng Jan 31 '19 at 17:02
  • Thanks! This is exactly what I need to get access from another trusted account! – Andrew Saushkin Dec 25 '19 at 09:27
  • Hi @Raymond Ng Are you able to solve the problem, I have same requirements and stuck, can you please update. – TechMaster Jun 16 '21 at 15:03