aws / amazon-eks-pod-identity-webhook

Amazon EKS Pod Identity Webhook
Apache License 2.0
611 stars 175 forks source link

Feature: setting `AWS_ROLE_SESSION_NAME` to pod name #112

Open danopia opened 3 years ago

danopia commented 3 years ago

What would you like to be added:

I would like the webhook to also attach a AWS_ROLE_SESSION_NAME envvar to the mutated pods. The downward API can be used to inject metadata.name as the actual value, so each pod reliably gets its own name, but other approaches are reasonable too.

Why is this needed:

Currently, AWS does not know the identity of the Pod assuming the role, just the ServiceAccount. So when multiple pods are doing actions it's nearly impossible to correlate CloudTrail events with an individual Pod, which would be useful when following application logs or other debugging activities.

Consider this CloudTrail event:

{
    "eventVersion": "1.08",
    "userIdentity": {
        "type": "WebIdentityUser",
        "principalId": "arn:aws:iam::[redacted]:oidc-provider/[redacted]:sts.amazonaws.com:system:serviceaccount:frontend:api",
        "userName": "system:serviceaccount:frontend:api",
        "identityProvider": "arn:aws:iam::[redacted]:oidc-provider/[redacted]"
    },
    "eventTime": "2021-04-17T08:42:34Z",
    "eventSource": "sts.amazonaws.com",
    "eventName": "AssumeRoleWithWebIdentity",
    "userAgent": "aws-sdk-nodejs/2.802.0 linux/v14.15.1 callback",
    "requestParameters": {
        "roleArn": "arn:aws:iam::[redacted]:role/kubernetes/frontend/api",
        "roleSessionName": "token-file-web-identity"
    },
    "responseElements": {
        "provider": "arn:aws:iam::[redacted]:oidc-provider/[redacted]",
        "subjectFromWebIdentityToken": "system:serviceaccount:frontend:api",
        "audience": "sts.amazonaws.com",
        "assumedRoleUser": {
            "assumedRoleId": "AROA[redacted]:token-file-web-identity",
            "arn": "arn:aws:sts::[redacted]:assumed-role/api/token-file-web-identity"
        }
    },
    [redacted]
}

There's a whole bunch of identifiers there, none of which know more from Kubernetes beyond the namespace and service account. The session name defaults to token-file-web-identity which is the NodeJS SDK's behavior, while I believe other SDKs (such as golang) have a different default string there.

Now let's inject AWS_ROLE_SESSION_NAME via https://github.com/danopia/amazon-eks-pod-identity-webhook/commit/2ec3516b840e08257cb58d4694123e55bc06eefe and these particular fields change:

{
    "requestParameters": {
        "roleArn": "arn:aws:iam::[redacted]:role/kubernetes/frontend/api",
        "roleSessionName": "api-d59cf9bbc-pnmds"
    },
    "responseElements": {
        "assumedRoleUser": {
            "assumedRoleId": "AROA[redacted]:api-d59cf9bbc-pnmds",
            "arn": "arn:aws:sts::[redacted]:assumed-role/api/api-d59cf9bbc-pnmds"
        }
    },
}

Now STS is informed about the pod name and CloudTrail activity can be correlated with individual pods 😄 in this case api-d59cf9bbc-pnmds

Considerations:

  1. Individual deployments can already set this envvar directly if desired. I suggest that the Webhook perform this mutation because I see very little reason to not supply a custom session-name.
  2. If some cluster operators don't want this, then it would need to be feature gated. I patch I linked above (based on a quite-old git history) does not have gating and thus I didn't file a PR with it as-is.
    • Given that any existing value is honored, I can't see how this would be a breaking change. Perhaps if an IAM policy grants/denies based on the default value of SessionName, which just sounds brittle.
  3. Perhaps namespace/pod would be more useful, or even namespace/pod/container; however the downwards API won't be useful for that. I've been happy with just podname.
  4. Perhaps STS's very new SourceIdentity field is a better place for this. I don't see how it can be set during a AssumeRoleWithWebIdentity call, and this would probably involve an SDK change which is much more of an ask.
reegnz commented 3 years ago

TBQH I would prefer to see the identity in the AWS_ROLE_SESSION_NAME, eg. namespace/service_account_name, since getting direct identity info is more important to me than an ephemeral pod name.

orf commented 3 years ago

To me it would be good to be able to specify specific tags with a session.

For example you might have a CI setup in k8s. The pod definition is fixed but the code could be untrusted. Being able to add a “project=Foo” tag to the web identity file would allow tag based access control in other resources when using a shared service account.

reegnz commented 3 years ago

BTW this is how I do it today with Downward API:

env:
- name: POD_SA_NAME
  valueFrom:
    fieldRef:
      fieldPath: spec.serviceAccountName
- name: POD_NAMESPACE
  valueFrom:
    fieldRef:
      fieldPath: metadata.namespace
- name: AWS_ROLE_SESSION_NAME
  value: system.serviceaccount.$(POD_NAMESPACE).$(POD_SA_NAME)

Then I get almost the same value as AWS_ROLE_SESSION_NAME as the sub in the JWT. (Except that instead of : I have to use . because : is an invalid character for session name).

orf commented 3 years ago

The problem is this is still user controlled - you can assume the role with any session name or mimic another pod.

reegnz commented 3 years ago

@orf I think what you're talking about would only be doable with either additional JWT claims (needs changes to k8s upstream) and changes on how those claims are consumed by AWS (needs changes on AWS STS service). I don't think the pod identity webhook can do anything about that.

As of right now AWS_ROLE_SESSION_NAME is just a convenience and the pod identity webhook won't be able to enforce what this is set to, it needs to be enforced on IAM level.

I imagine one could do something like this in the trust relationship:

     "Condition": {
        "StringEquals": {
          "xxx.s3.amazonaws.com:sub": "{sts:RoleSessionName}"
        }
      }

But for that to work, the role session name would have to allow : character as well, which is an API limitation currently. But that would then enforce that AWS_ROLE_SESSION_NAME must match the sub claim in the JWT.

At this point these are either limitations of kubernetes projected service account tokens or the AWS STS API, so I don't think it makes sense to track that issue in this project.

orf commented 3 years ago

Ok! Thank you for the clarifications, that makes sense. You might be able to use session tags instead of the RoleSessionName to avoid the : character limitation?

But yes, this does seem not worth tracking here. Sorry for the noise!

plazma-prizma commented 6 months ago

Hello, we need to override the RoleSessionName (AWS_ROLE_SESSION_NAME) to modify the ARN of the AWS_ROLE_ARN when the requests are sent. Could we resurrect this thread and bring this option in?