Aws-iam-authenticator: Automap IAM ARNs to username for allowed accounts

Created on 13 Dec 2017  路  20Comments  路  Source: kubernetes-sigs/aws-iam-authenticator

Provide an option that when enabled, maps the IAM ARN for a user to their username automatically, without the need to setup a account mapping. The IAM ARN can be used in RBAC RoleBindings as the username, or another authorizer could be used that understands what kubernetes resources a IAM identity has access to. If a user wishes to use groups, or shorter usernames, they would still be able to with the user/role mappings. While this makes any user/role an authenticated user to kubernetes, it does not provide access to resources when used in conjunction with an authorizer (RBAC for example).

This would add two fields to the server config: mapIAMToUsername bool to turn the feature on and mappedAccounts as a list of strings containing IAM identities to handle automatically.

It would only automap an identity if the user/role ARN was not in a explicit mapping. If an explicit mappings exists but only provides groups and not a username, the IAM ARN would be used for the username.

kinfeature

Most helpful comment

As a potential new user of authenticator I have to say I'm very confused by this section of the config. Just like @mumoshu I have a federated log on and I wish there was a better write up on how to implement this section of the config file for me. Do the groups come from the federated login? How do you map this to RBAC groups and roles?

All 20 comments

+1

Maybe we don't even need the mapIAMToUsername boolean, just a list mappedAccounts (or userMappedAccounts?) that's empty by default?

+1 I like just having the mappedAccounts list.

Since account is an overloaded term, want to confirm that accounts here mean AWS Accounts. Would the config be extended to add AWS Account IDs that are allowed without an explicit mapping?
e.g.

  mappedAccounts:
  - "123456789012"
  - "456789012345"

Opened https://github.com/heptio/authenticator/pull/50 based on my interpretation of this issue. Please review.

@Sushant I'm interested in this feature too, and thanks a lot for your PR!

If I read the current implementation correctly, we don't yet have a user/role mapping thru templating, right?

Would there be any concern you want to leave me, before I make a PR? 馃槃
Thx.

user/role mapping thru templating

Let me clarify a bit more about this.

Currently, anyone like me relying on a SSO to get a AWS session would have a caller-identity like:

$ aws sts get-caller-identity
{
    "UserId": "RANDOMSTRING:[email protected]",
    "Account": "012345678901",
    "Arn": "arn:aws:sts::012345678901:assumed-role/myIamGroupNameFooDeveloper/[email protected]"
}

This is where things get fancy: I want e.g.:

  • FooDeveloper to be a K8S group assigned to my user, whereas myIamGroupNameFooDeveloper is the full name of the IAM role which can be parsed out from Arn
  • mumoshu to be a K8S user assigned to me, whereas [email protected] is the full IAM session name which can be parsed out from Arn

Actually this use-case is why I've contributed #14 before.
mapAccounts seems to supercede it once I implemented the template-based user/role mapping feature on top.

An alternative approach would be to extend where role mappings are applicable. Rather than writing it in mapAccounts:

 mapRoles:
     # NEW! accountId is specified instead of roleArn
  - accountID: "012345678901"
    username: "aws:{{AccountID}}:instance:{{SessionName}}"
    groups:
    - "system:{{RoleName | lc}}"

In this case I need to:

  • Enhance renderTemplate to support extracting only role name from an arn
  • Add AccountID to RoleMapping and make it configurable via yaml through viper

I began to think that the current distinction among mapRoles vs mapUsers vs mapAccounts confusing:

  • mapRoles(map iam session/role to k8s user/group dynamically)
  • mapUsers(map iam user to k8s user/group statically)
  • mapAccounts(map iam session/role to k8s user/group dynamically for aws account)

Can't we just merge them into a single mappings like the below?

server:
  # each mappings entry maps an IAM session/role to a Kubernetes username and set of groups
  mappings:
  # Each username and group can optionally contain template parameters:
  #  1) "{{AccountID}}" is the 12 digit AWS ID.
  #  2) "{{SessionName}}" is the role session name.
  # statically map arn:aws:iam::000000000000:role/KubernetesAdmin to cluster admin
  - roleARN: arn:aws:iam::000000000000:role/KubernetesAdmin
    username: kubernetes-admin
    groups:
    - system:masters

  # map EC2 instances in my "KubernetesNode" role to users like
  # "aws:000000000000:instance:i-0123456789abcdef0". Only use this if you
  # trust that the role can only be assumed by EC2 instances. If an IAM user
  # can assume this role directly (with sts:AssumeRole) they can control
  # SessionName.
  - roleARN: arn:aws:iam::000000000000:role/KubernetesNode
    username: aws:{{AccountID}}:instance:{{SessionName}}
    groups:
    - system:bootstrappers
    - aws:instances

  # map federated users in my "KubernetesAdmin" role to users like
  # "admin:alice-example.com". The SessionName is an arbitrary role name
  # like an e-mail address passed by the identity provider. Note that if this
  # role is assumed directly by an IAM User (not via federation), the user
  # can control the SessionName.
  - roleARN: arn:aws:iam::000000000000:role/KubernetesAdmin
    username: admin:{{SessionName}}
    groups:
    - system:masters

  # map user IAM user Alice in 000000000000 to user "alice" in group "system:masters"
  - userARN: arn:aws:iam::000000000000:user/Alice
    username: alice
    groups:
    - system:masters

  # automatically map IAM ARN from these accounts to username.
  # NOTE: Always use quotes to avoid the account numbers being recognized as numbers
  # instead of strings by the yaml parser.
  - accountID: "012345678901"
    username: developer:{{SessionName}}
    groups:
    - developers

Personally, I even prefer a syntax like the below to clearly differentiate the "source" and "target" of a mapping :)

server:
  mappings:
  - fromAWS:
      roleARN: arn:aws:iam::000000000000:role/KubernetesAdmin
    toK8S:
      username: kubernetes-admin
      groups:
      - system:masters

  - fromAWS:
      roleARN: arn:aws:iam::000000000000:role/KubernetesNode
    toK8S:
      username: aws:{{AccountID}}:instance:{{SessionName}}
      groups:
      - system:bootstrappers
      - aws:instances

  - fromAWS:
      accountID: "012345678901"
    toK8S:
      username: developer:{{SessionName}}
      groups:
      - developers

We might be worrying about such radical change would result in the configuration syntax more confusing or bloated.

I think it is rather the opposite - what we have today: mapRoles, mapUsers, and mapAccounts seems ambiguous and confusing to "me".

I can't concisely see what is mapped to what from those setting keys, and some other nits are:

In nutshell, we have three too divergent flavors of configuration syntax of mapRoles, mapUsers, mapAccounts.

They are ambiguous about what is mapped to what.

Also some nits:

  • Currently there's no way for an user to figure out which is dynamic or static. More concretely, mapRoles maps IAM session names to K8S user/group "dynamically" using templates, while mapUsers maps IAM user to K8S uesr/group statically.
  • Regarding mapAccounts, it provides no way to customize which IAM session is mapped to which k8s user. In that sense, it is like a static mapping. The mapping is literally hard-coded though. I couldn't stop expecting mapAccounts to be a generalized version of mapRoles at glance, which isn't true

TL;DR; I am already confused as an user 馃槈
To add some more context, AFAICS, there was no such confusion I remember when we had done #14 and #15 in the very beginning of the project.

But the situation has changed since then.
It is time to redesign the configuration syntax!

You have some good ideas, and I agree that the config is confusing right now. I agree that the fact that users being static and roles being dynamic is a bit confusing. Unfortunately, we actually have a significant number of users on EKS using the authenticator. So, I could definitely see a syntax change in a V2, but until then I think we need to be mostly add-only to the user config.

As a potential new user of authenticator I have to say I'm very confused by this section of the config. Just like @mumoshu I have a federated log on and I wish there was a better write up on how to implement this section of the config file for me. Do the groups come from the federated login? How do you map this to RBAC groups and roles?

Commenting on this issue, since this seems the most related. I too, are a fairly new user of the Heptio Authenticator with Kops. Which works great, and is fairly easy to setup. Thank you for that!

We are also using the federated log-on, leveraging the aws-google-auth project by cevoaustrailia. Link: https://github.com/cevoaustralia/aws-google-auth

I have issues with getting the email information into the audit logs of k8s.

$ aws sts get-caller-identity
{
    "Account": "123456789",
    "UserId": "RANDOMSTRING:[email protected]",
    "Arn": "arn:aws:sts::123456789:assumed-role/AssumedRole/[email protected]"
}

I would like to extract the email of the developer assuming the role, and pass it to the username field in the mapRoles configuration:

      mapRoles:
      - roleARN: arn:aws:iam::123456789:role/KubernetesAdmin
        username: "kubernetes-dev:{{UserID}}"
        groups:
        - aws:kubernetes:dev

Where UserID should be the email, or just the UserId from the get-identity request. The complete Arn would also be an option.

I'm not sure whether or not, it's just me that don't quite understand how the mapping works, or if it's not possible at the moment.

@kaspernissen

With mapRoles you can use the Session Name (in this case [email protected]) by placing {{SessionName}} in the mapping.

This should give you what you want.

      mapRoles:
      - roleARN: arn:aws:iam::123456789:role/KubernetesAdmin
        username: "kubernetes-dev:{{SessionName}}"
        groups:
        - aws:kubernetes:dev

@mattlandis
Forgot to mention that I've already tried with {{SessionName}} exactly as your example which results in the following being audit logged:

user.uid | heptio-authenticator-aws:ACCOUNT_NUMBER:AROAIZXXXXXXXXXXXXXXX
user.username | kubernetes-dev:1527080XXXXXXXXXXXX

I don't see the UserId or complete Arn being parsed to the logs. Maybe I have misconfigured something elsewhere. 馃

I just updated to 0.3.0, and still only see the above as user.uid and user.username when using the following configuration. Any ideas on what I'm missing is much appreciated?

apiVersion: v1
kind: ConfigMap
metadata:
  namespace: kube-system
  name: heptio-authenticator-aws
  labels:
    k8s-app: heptio-authenticator-aws
data:
  config.yaml: |
    clusterID: k8s.dev.example.com
    server:
      mapRoles:
      - roleARN: arn:aws:iam::<ACCOUNT_ID>:role/KubernetesAdmin
        username: "kubernetes-admin:{{SessionName}}"
        groups:
        - aws:kubernetes:admin

      - roleARN: arn:aws:iam::<ACCOUNT_ID>:role/KubernetesDev
        username: "kubernetes-dev:{{SessionName}}"
        groups:
        - aws:kubernetes:dev

      - roleARN: arn:aws:iam::<ACCOUNT_ID>:role/KubernetesView
        username: "kubernetes-view::{{SessionName}}"
        groups:
        - aws:kubernetes:view

      - roleARN: arn:aws:iam::<ACCOUNT_ID>:role/KubernetesCD
        username: "kubernetes-cd::{{SessionName}}"
        groups:
        - aws:kubernetes:cd

      mapAccounts:
      - "<ACCOUNT_ID>"

What do the authenticator logs look like? There should be a line that says the ARN was mapped to a username and groups.

There is, however it seems that the specific user information assuming the role is lost.

heptio-authenticator logs:

time="2018-06-13T06:42:57Z" level=info msg="mapping IAM role" groups="[aws:kubernetes:admin]" role="arn:aws:iam::<ACCOUNT_ID>:role/KubernetesAdmin" username="kubernetes-admin:{{SessionName}}"
time="2018-06-13T06:42:57Z" level=info msg="mapping IAM role" groups="[aws:kubernetes:dev]" role="arn:aws:iam::<ACCOUNT_ID>:role/KubernetesDev" username="kubernetes-dev:{{SessionName}}"
time="2018-06-13T06:42:57Z" level=info msg="mapping IAM role" groups="[aws:kubernetes:view]" role="arn:aws:iam::<ACCOUNT_ID>:role/KubernetesView" username="kubernetes-view::{{SessionName}}"
time="2018-06-13T06:42:57Z" level=info msg="mapping IAM role" groups="[aws:kubernetes:cd]" role="arn:aws:iam::<ACCOUNT_ID>:role/KubernetesCD" username="kubernetes-cd::{{SessionName}}"
time="2018-06-13T06:42:57Z" level=info msg="mapping IAM Account" accountID=<ACCOUNT_ID>
time="2018-06-13T06:42:57Z" level=info msg="loaded existing keypair" certPath=/var/heptio-authenticator-aws/cert.pem keyPath=/var/heptio-authenticator-aws/key.pem
time="2018-06-13T06:42:57Z" level=info msg="listening on https://127.0.0.1:21362/authenticate"
time="2018-06-13T06:42:57Z" level=info msg="reconfigure your apiserver with `--authentication-token-webhook-config-file=/etc/kubernetes/heptio-authenticator-aws/kubeconfig.yaml` to enable (assuming default hostPath mounts)"
time="2018-06-13T06:42:59Z" level=info msg="access granted" arn="arn:aws:iam::<ACCOUNT_ID>:role/KubernetesAdmin" client="127.0.0.1:59960" groups="[aws:kubernetes:admin]" method=POST path=/authenticate uid="heptio-authenticator-aws:<ACCOUNT_ID>:AROAIZ42PN52IBRFMXHF4" username="kubernetes-admin:1528872177244823900"

Which results in the user.username field in the audit log being, e.g. kubernetes-admin:1528872177244823900.

Can you actually create a new issue if you don't mind? This one is more of a proposal, and you are troubleshooting an issue.

Can someone suggest me something that works? This is what my configmap looks like:

 mapRoles: | 
   - groups:
      - curefit:eks-admin
      rolearn: arn:aws:iam::000000000:role/eks-admins
      username: admin:{{SessionName}}
    - groups:
      - curefit:eks-viewer
      rolearn: arn:aws:iam::000000000:role/eks-all-cluster-viewers-role
      username: viewer:{{SessionName}}

This role is associated with a policy, that is attached to a group, and no one from that group is able to access the cluster.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rajal-amzn picture rajal-amzn  路  3Comments

davidham picture davidham  路  12Comments

psaffrey-origami picture psaffrey-origami  路  8Comments

kwerey picture kwerey  路  7Comments

plumdog picture plumdog  路  10Comments