Search code examples
amazon-cognitoamazon-iamassume-role

Is it possible to create a trust that allow federated users from cognito to assume role according to a custom attribute?


Is it possible to create a trust that allow federated users from cognito to assume role according to a custom attribute?

For example with a tenant attribute:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Federated": "cognito-identity.amazonaws.com"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "cognito-identity.amazonaws.com:aud": "us-east-1:12345678-corner-cafe-123456790ab"
        },
        "ForAnyValue:StringLike": {
          "cognito-identity.amazonaws.com:amr": "unauthenticated"
        },
        "ForAnyValue:StringLike": {
          "cognito-identity.amazonaws.com:custom:tenant": "tenant-name"
        }
      }
    }
  ]
}

I'm using get_credentials_for_identity api with cognito token to assume this role.


Solution

  • Yes, this is definitely possible with attributes for access control. This will only work for an authenticated user (you need an ID token to map claims to principal tags).

    1. Your trust policy needs to looks like this:
    {
        "Statement": [
            {
                "Effect": "Allow",
                "Action": [
                    "sts:AssumeRoleWithWebIdentity",
                    "sts:TagSession"
                ],
                "Condition": {
                    "StringEquals": {
                        "cognito-identity.amazonaws.com:aud": "us-east-1:12345678-corner-cafe-123456790ab"
                    },
                    "ForAnyValue:StringLike": {
                        "cognito-identity.amazonaws.com:amr": "authenticated"
                    }
                },
                "Principal": {
                    "Federated": "cognito-identity.amazonaws.com"
                }
            }
        ]
    }
    

    The difference is the sts:TagSession action and the fact that amr must be authenticated.

    1. Policy for assumed role will look something like this:
    {
        "PolicyDocument": {
            "Statement": [
                {
                    "Action": "s3:GetObject",
                    "Effect": "Allow",
                    "Resource": "arn:aws:s3:::your-bucket-name/cognito/attributes/by_family_name/${aws:PrincipalTag/family_name}/*"
                },
                {
                    "Action": "s3:GetObject",
                    "Condition": {
                        "StringEquals": {
                            "s3:ExistingObjectTag/given_name": "${aws:PrincipalTag/given_name}"
                        }
                    },
                    "Effect": "Allow",
                    "Resource": "arn:aws:s3:::your-bucket-name/cognito/attributes/by_tag/*"
                }
            ],
            "Version": "2012-10-17"
        },
        "PolicyName": "attributes-policy"
    }
    
    1. You need to configure your Cognito (or any other) provider in Identity Pool to do the mapping between claims from the token to tags. You can do it in console under Attributes for access control. Or with CLI like this:
    aws cognito-identity set-principal-tag-attribute-map --cli-input-json file://set-principal-tag-attribute-map.json
    

    Where set-principal-tag-attribute-map.json would look something like this (for Cognito as IDP):

    {
        "IdentityPoolId": "here-is-your-identity-pool-id",
        "IdentityProviderName": "cognito-idp.<region>.amazonaws.com/<user_pool_id>",
        "UseDefaults": false,
        "PrincipalTags": {
            "given_name": "given_name",
            "family_name": "family_name"
        }
    }
    

    You can find more details in documentation here: https://docs.aws.amazon.com/cognito/latest/developerguide/attributes-for-access-control.html