Search code examples
amazon-web-servicesaws-cli

Get AWS Principal Tag Value of a Federated User


We are using AWS SSO with an External Identity Provider and have enabled ABAC (Attributes for Access Control). We are passing some session tags like SSMSessionRunAs. Can we get the value of the session/principal tag being passed via AWS CLI assuming that the user currently configured in the shell is the Federated user?


Solution

  • Though you're passing session tags via AWS SSO (IAM Identity Center), the general question is whether it is possible to get the value of an AWS session tag.

    There seems to be no way to get the full set of AWS session tags, neither via an API call nor in the console. Rather, it is only possible to get partial visibility into the current AWS session tags in two ways:

    1. Examine CloudTrail logs. This only shows you new tags being explicitly applied to newly created sessions, as well as incoming transitive session tags.

    2. Write IAM policies to allow/deny access using a Condition clause with ${principalTag/TAG_NAME}.

    1. CloudTrail Logs

    CloudTrail logs show a subset of session tags when the following API calls are made: AssumeRole, AssumeRoleWithSAML, AssumeRoleWithWebIdentity, and GetFederationToken (ref: Passing session tags in AWS STS)

    In the corresponding CloudTrail events, you see:

    • Tags explicitly passed in the API call which apply to the new session; and
    • Incoming transitive session tags, which propagate to the new session. (Does not apply to AssumeRoleWithSAML and AssumeRoleWithWebIdentity, which are called without an existing session.)

    However, these CloudTrail events do not include current, non-transitive session tags, which are not inherited by the new session. (If there is a way to see them, I would like to know...)

    Example

    Here is an excerpt showing requestParameters from a CloudTrail event for an AssumeRole call:

    "requestParameters": {
        "incomingTransitiveTags": {
            "TagKey1": "TagValue1"
        },
        "roleArn": "arn:aws:iam::XXXXXXXXXXXX:role/TestTagRole1",
        "roleSessionName": "some-role-session-name",
        "tags": [
            {
                "key": "TagKey4",
                "value": "TagValue4"
            },
            {
                "key": "TagKey5",
                "value": "TagValue5"
            }
        ]
        "transitiveTagKeys": [
            "TagKey4"
        ]
    }
    

    It reveals the following:

    • The call is made from a session which has the TagKey1: TagValue1 transitive session tag.
    • The call explicitly applies tags to the new session: TagKey4: TagValue4; TagKey5: TagValue5
    • The new session tag TagKey4: TagValue4 is transitive.

    However, the event entry does not show the following:

    • The call is made from a session which also has two non-transitive session tags: TagKey2: TagValue2; TagKey3: TagValue3
    • TagKey2 was explicitly passed via a previous AssumeRole* call, and thus appears in an earlier CloudTrail event.
    • TagKey3 was implicitly applied via an IAM user/role tag and as such does not appear on any visible session record (to my knowledge).

    Aside: Programmatic access to CloudTrail

    While CloudTrail can also be accessed via an API, there is a delay of several minutes for an event to appear in its event history, which seems to make it infeasible to test for session tags programmatically in real-time.

    2. IAM policies

    You could make use of IAM policies which allow or deny based on ${principalTag/TAG_NAME}. For instance, the below policy will allow the listing of S3 objects if the S3 prefix matches the value of session tag SessionTag:

    {
        "Version": "2012-10-17",
        "Statement": {
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": "*",
            "Resource": "arn:aws:s3:::session-tags-test",
            "Condition": {
                "StringEquals": {
                    "s3:prefix": "${aws:PrincipalTag/SessionTag}"
                }
            }
        }
    }
    

    Then, it is possible to test for an exact value of a current session tag SessionTag by attempting to list objects:

    $ aws s3api list-objects --bucket session-tags-test --prefix SessionTagValue
    
    $ aws s3api list-objects --bucket session-tags-test --prefix IncorrectValue
    An error occurred (AccessDenied) when calling the ListObjects operation: Access Denied
    

    Alternatively, to test for the presence of SessionTag, regardless of its value, the Condition element in the above policy can be adjusted to use the Null condition operator:

    "Condition": {
        "Null": {
            "aws:PrincipalTag/SessionTag": "false"
        }
    }