I want to be able to generate a cognito userl pool with standard attributes through serverless
Standard attributes from cognito user pool
As you can see I have defined the following schema:
Schema:
- Name: uuid
AttributeDataType: String
Mutable: true
- Name: name
AttributeDataType: String
Mutable: true`
But it is not working.
`Resources:
QuizCardsUserPool:
Type: AWS::Cognito::UserPool
Properties:
AccountRecoverySetting:
RecoveryMechanisms:
- Name: 'verified_email'
Priority: 1
# AdminCreateUserConfig:
# InviteMessageTemplate:
# EmailMessage: 'Your username is {username} and temporary password is {####}.'
AutoVerifiedAttributes:
- 'email'
# EmailVerificationMessage: 'email message: {####}'
# EmailVerificationSubject: 'email subject: {####}'
UsernameAttributes:
- 'email'
UsernameConfiguration:
CaseSensitive: false
UserPoolName: ${sls:stage}-quizcards
Policies:
PasswordPolicy:
MinimumLength: 8
RequireLowercase: false
RequireNumbers: false
RequireSymbols: false
RequireUppercase: false
TemporaryPasswordValidityDays: 1
Schema:
- Name: uuid
AttributeDataType: String
Mutable: true
- Name: name
AttributeDataType: String
Mutable: true
# Creates a User Pool Client to be used by the identity pool
QuizCardsUserPoolClient:
Type: AWS::Cognito::UserPoolClient
Properties:
ClientName: quizcards-client
GenerateSecret: false
UserPoolId: !Ref QuizCardsUserPool
ReadAttributes:
- "name"
- "email"
- "profile"
- "preferred_username"
WriteAttributes:
- "name"
- "email"
- "profile"
- "preferred_username"
# Creates a federated Identity pool
QuizCardsIdentityPool:
Type: AWS::Cognito::IdentityPool
Properties:
AllowClassicFlow: true
IdentityPoolName: ${sls:stage}-quizcards
AllowUnauthenticatedIdentities: false
CognitoIdentityProviders:
- ClientId: !Ref QuizCardsUserPoolClient
ProviderName: !GetAtt QuizCardsUserPool.ProviderName
# Create a role for unauthorized access to AWS resources. Very limited access. Only allows users in the previously created Identity Pool
CognitoUnAuthorizedRole:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: 'Allow'
Principal:
Federated: 'cognito-identity.amazonaws.com'
Action:
- 'sts:AssumeRoleWithWebIdentity'
Condition:
StringEquals:
'cognito-identity.amazonaws.com:aud': !Ref QuizCardsIdentityPool
'ForAnyValue:StringLike':
'cognito-identity.amazonaws.com:amr': unauthenticated
Policies:
- PolicyName: 'CognitoUnauthorizedPolicy'
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: 'Allow'
Action:
- 'mobileanalytics:PutEvents'
- 'cognito-sync:*'
Resource: '*'
# Create a role for authorized access to AWS resources. Control what your user can access. This example only allows Lambda invocation
# Only allows users in the previously created Identity Pool
CognitoAuthorizedRole:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: 'Allow'
Principal:
Federated: 'cognito-identity.amazonaws.com'
Action:
- 'sts:AssumeRoleWithWebIdentity'
Condition:
StringEquals:
'cognito-identity.amazonaws.com:aud': !Ref QuizCardsIdentityPool
'ForAnyValue:StringLike':
'cognito-identity.amazonaws.com:amr': authenticated
Policies:
- PolicyName: 'CognitoAuthorizedPolicy'
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: 'Allow'
Action:
- 'mobileanalytics:PutEvents'
- 'cognito-sync:*'
- 'cognito-identity:*'
Resource: '*'
- Effect: 'Allow'
Action:
- 'lambda:InvokeFunction'
Resource: '*'
# - Effect: "Allow"
# Action:
# - "s3:ListBucket"
# - "s3:GetObject"
# - "s3:PutObject"
# - "s3:DeleteObject"
# Resource:
# - "arn:aws:s3:::husjournalen-property-docs/*"
# Assigns the roles to the Identity Pool
QuizCardsIdentityPoolRoleAttachment:
Type: AWS::Cognito::IdentityPoolRoleAttachment
Properties:
IdentityPoolId: !Ref QuizCardsIdentityPool
Roles:
authenticated: !GetAtt CognitoAuthorizedRole.Arn
unauthenticated: !GetAtt CognitoUnAuthorizedRole.Arn
Outputs:
UserPoolId:
Value: !Ref QuizCardsUserPool
Export:
Name: 'UserPool::Id'
UserPoolClientId:
Value: !Ref QuizCardsUserPoolClient
Export:
Name: 'UserPoolClient::Id'
IdentityPoolId:
Value: !Ref QuizCardsIdentityPool
Export:
Name: 'IdentityPool::Id'
I have tried to find some information regarding these attributes.
As you can see in this link from AWS documentation
Schema
An array of schema attributes for the new user pool. These attributes can be standard or custom attributes.
Type: Array of SchemaAttributeType objects
Array Members: Minimum number of 1 item. Maximum number of 50 items.
Required: No
I don´t know what else could I be missing here
Related
I have the following SAM template:
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
test lambda
Globals:
Function:
Timeout: 3
Tracing: Active
Api:
TracingEnabled: True
Resources:
NotesFunction:
Type: AWS::Serverless::Function
Properties:
PackageType: Zip
CodeUri: notes/
Handler: app.lambdaHandler
Runtime: nodejs18.x
Policies:
- AmazonDynamoDBFullAccess
Architectures:
- x86_64
Events:
FetchNotes:
Type: Api
Properties:
Path: /notes
Method: get
GiveNotes:
Type: Api
Properties:
Path: /notes
Method: post
Users:
Type: Api
Properties:
Path: /notes/users
Method: get
Metadata:
BuildMethod: esbuild
BuildProperties:
Minify: true
Target: "es2020"
Sourcemap: true
EntryPoints:
- app.ts
KmsKey:
Type: AWS::KMS::Key
Properties:
Description: CMK for encrypting and decrypting
KeyPolicy:
Version: '2012-10-17'
Id: key-default-1
Statement:
- Sid: Enable IAM User Permissions
Effect: Allow
Principal:
AWS: !Sub arn:aws:iam::${AWS::AccountId}:root
Action: kms:*
Resource: '*'
- Sid: Allow administration of the key
Effect: Allow
Principal:
AWS: arn:aws:iam::<MY_ACCOUNT>:role/aws-service-role/cks.kms.amazonaws.com/KMSKeyAdminRole
Action:
- kms:Create*
- kms:Describe*
- kms:Enable*
- kms:List*
- kms:Put*
- kms:Update*
- kms:Revoke*
- kms:Disable*
- kms:Get*
- kms:Delete*
- kms:ScheduleKeyDeletion
- kms:CancelKeyDeletion
Resource: '*'
- Sid: Allow use of the key
Effect: Allow
Principal:
AWS: !Ref NotesFunctionRole
Action:
- kms:DescribeKey
- kms:Encrypt
- kms:Decrypt
- kms:ReEncrypt*
- kms:GenerateDataKey
- kms:GenerateDataKeyWithoutPlaintext
Resource: '*'
NotesDynamoDB:
Type: AWS::DynamoDB::Table
Properties:
TableName: experimental-notes
AttributeDefinitions:
- AttributeName: id
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: 5
WriteCapacityUnits: 5
StreamSpecification:
StreamViewType: NEW_IMAGE
Outputs:
NotesApi:
Description: "API Gateway endpoint URL for dev stage for Notes function"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/dev/notes/"
NotesFunction:
Description: "Notes Lambda Function ARN"
Value: !GetAtt NotesFunction.Arn
NotesFunctionIamRole:
Description: "Implicit IAM Role created for Notes function"
Value: !GetAtt NotesFunctionRole.Arn
NotesDynamoDB:
Description: "DynamoDB table backing the Lambda"
Value: !GetAtt NotesDynamoDB.Arn
When I build + deploy this template I get the following CloudFormation errors:
Resource handler returned message: "Policy contains a statement with one or more invalid principals....
Obviously I have redacted my actual account ID and replaced it with <MY_ACCOUNT> (!).
But it doesn't say what's "invalid" about which principals. The idea is that the 2nd policy statement gets applied/hardcoded to an existing role (KMSKeyAdminRole). And that the 3rd Statement gets applied to the role of the NotesFunction Lambda created up above.
Can anyone spot where I'm going awry?
This ended up working perfectly and fixing the CF error:
- Sid: Allow use of the key
Effect: Allow
Principal:
AWS: !GetAtt FeedbackFunctionRole.Arn
Action:
- kms:DescribeKey
- kms:Encrypt
- kms:Decrypt
- kms:ReEncrypt*
- kms:GenerateDataKey
- kms:GenerateDataKeyWithoutPlaintext
Resource: '*'
Use this https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_testing-policies.html to test if your policies are valid
I'm trying to create a admin API using api gateway, lambda and dynamoDB. I want only the logged in users in certain group be able to access lambda.
I see that the lambda would not assume role of the cognito user and access the dynamoDB. API only works if I attach the dynamoDB policy to the LambdaRole.
Is there a way for this to work dynamically based on user groups. Do I need to add this assumeRole logic in the lambda handler itself ? Please help
This is the ERROR I get when I git my API from postman with Authorization tokens
{
"message": "User: arn:aws:sts::09723XXXXX357:assumed-role/tango-admin-lambda-role/tango-admin-service-dev-getActiveOrders is not authorized to perform: dynamodb:Query on resource: arn:aws:dynamodb:us-east-1:09723XXXXX357:table/dev-tango-service-tango-order-db",
"code": "AccessDeniedException",
"time": "2022-05-23T18:42:39.241Z",
"requestId": "DDK7AS6SBO8D0U3KXXXXXXXX",
"statusCode": 400,
"retryable": false,
"retryDelay": 46.2351059972586
}
Here is my serverless.yml file
service: tango-admin-service
provider:
name: aws
runtime: nodejs14.x
region: us-east-1
environment:
DYNAMODB_TABLE: ${opt:stage, self:provider.stage}-tango-service-tango-order-db
# functions
functions:
hello:
handler: src/handlers/hello.handler
events:
- http:
path: hello
method: get
getActiveOrders:
handler: src/handlers/getActiveOrders.handler
role: TangoAdminLambdaRole # How can this role be assume from Congito ? It only works if I directly pass the Role with DynamoDB Policy
events: # The events that trigger this function
- http:
path: get-active-orders
method: post
cors: true
authorizer:
type: COGNITO_USER_POOLS
authorizerId:
Ref: TangoAdminApiAuthorizer
# Serverless plugins
plugins:
- serverless-plugin-typescript
- serverless-offline
resources:
Resources:
TangoAdminCognitoUserPool:
Type: AWS::Cognito::UserPool
Properties:
UserPoolName: TangoAdmin
TangoAdminCognitoUserPoolClient:
Type: AWS::Cognito::UserPoolClient
Properties:
ClientName: TangoAdminWebApp
GenerateSecret: false
UserPoolId:
Ref: "TangoAdminCognitoUserPool"
TangoAdminGroup:
Type: AWS::Cognito::UserPoolGroup
Properties:
GroupName: "TangoAdmin"
Description: "Admin group for Tango"
Precedence: 0
RoleArn: !GetAtt CognitoAdminIAMRole.Arn
UserPoolId:
Ref: "TangoAdminCognitoUserPool"
CognitoAdminIAMRole:
Type: AWS::IAM::Role
Properties:
RoleName: "tango-admin-role"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Federated:
- "cognito-identity.amazonaws.com"
Action:
- "sts:AssumeRoleWithWebIdentity"
Policies:
- PolicyName: "tango-admin-group-policy"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- "dynamodb:*"
Resource:
- "arn:aws:dynamodb:${opt:region, self:provider.region}:*:table/${self:provider.environment.DYNAMODB_TABLE}"
TangoAdminApiAuthorizer:
Type: AWS::ApiGateway::Authorizer
Properties:
Name: TangoAdmin
RestApiId:
Ref: ApiGatewayRestApi
Type: COGNITO_USER_POOLS
ProviderARNs:
- Fn::GetAtt: [ TangoAdminCognitoUserPool, Arn ]
IdentitySource: method.request.header.Authorization
TangoAdminLambdaRole:
Type: AWS::IAM::Role
Properties:
RoleName: "tango-admin-lambda-role"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action:
- "sts:AssumeRole"
Outputs:
TangoAdminCognitoUserPoolId:
Description: "Tango Admin Cognito User Pool ID"
Value:
Ref: "TangoAdminCognitoUserPool"
TangoAdminCognitoUserPoolClientId:
Description: "Tango Admin Cognito User Pool Client ID"
Value:
Ref: "TangoAdminCognitoUserPoolClient"
I am having trouble creating a stack with my CloudFormation template. When it reaches the IdentityPoolRoleAttachment I get the error:
Access to Role 'CognitoIdentityUnauthenticated' is forbidden. (Service: AmazonCognitoIdentity; Status Code: 400; Error Code: NotAuthorizedException; Request ID: 0866b3a1-15ab-11e9-82dd-1b30dc4a6a4d)
I've matched everything to what was created through the console and cannot figure out the problem. Can anyone see what I might be missing?
AWSTemplateFormatVersion: 2010-09-09
Description: AWS Script to create Cognito User and Identity pools
Resources:
CognitoUserPool:
Type: AWS::Cognito::UserPool
Properties:
UserPoolName: cognito-userpool
Schema:
- Name: email
AttributeDataType: String
Mutable: false
Required: true
Policies:
PasswordPolicy:
MinimumLength: 8
RequireLowercase: true
RequireNumbers: true
RequireUppercase: true
CognitoUserPoolClient:
Type: AWS::Cognito::UserPoolClient
Properties:
ClientName: cognito-app-client
ExplicitAuthFlows:
- ADMIN_NO_SRP_AUTH
GenerateSecret: false
ReadAttributes:
- email
RefreshTokenValidity: 30
UserPoolId: !Ref CognitoUserPool
CognitoIdentityPool:
Type: AWS::Cognito::IdentityPool
Properties:
IdentityPoolName: cognito_identity_pool
AllowUnauthenticatedIdentities: true
CognitoIdentityProviders:
- ClientId:
Ref: CognitoUserPoolClient
ProviderName:
Fn::GetAtt:
- CognitoUserPool
- ProviderName
CognitoIdentityAuthenticatedRole:
Type: AWS::IAM::Role
Properties:
RoleName: CognitoIdentityAuthenticated
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Federated: cognito-identity.amazonaws.com
Action: sts:AssumeRoleWithWebIdentity
Condition:
StringEquals:
"cognito-identity.amazonaws.com:aud":
Ref: CognitoIdentityPool
"ForAnyValue:StringLike":
"cognito-identity.amazonaws.com:amr": authenticated
CognitoIdentityUnauthenticatedRole:
Type: AWS::IAM::Role
Properties:
RoleName: CognitoIdentityUnauthenticated
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Federated: cognito-identity.amazonaws.com
Action: sts:AssumeRoleWithWebIdentity
Condition:
StringEquals:
"cognito-identity.amazonaws.com:aud":
Ref: CognitoIdentityPool
"ForAnyValue:StringLike":
"cognito-identity.amazonaws.com:amr": unauthenticated
# Create policy to allow authenticated user role to invode API lambda function
CognitoAuthInvokeLambdaPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: CognitoAuthInvokeLambdaPolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- mobileanalytics:PutEvents
- cognito-sync:*
- cognito-identity:*
Resource:
- "*"
- Effect: Allow
Action:
- execute-api:Invoke
Resource:
- "arn:aws:execute-api:us-east-1:*:xxxxxxxxxx/*"
- Effect: Allow
Action:
- "s3:*"
Resource:
- "*"
Roles:
- Ref: CognitoIdentityAuthenticatedRole
# Create policy to allow unauthenticated user role (currently only has access to Cognito - add additional resources if needed)
CognitoUnauthPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: CognitoUnauthPolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- mobileanalytics:PutEvents
- cognito-sync:*
- cognito-identity:*
Resource:
- "*"
Roles:
- Ref: CognitoIdentityUnauthenticatedRole
# Assigns the role to the Identity Pool
CognitoIdentityPoolRoleMapping:
Type: "AWS::Cognito::IdentityPoolRoleAttachment"
Properties:
IdentityPoolId: !Ref CognitoIdentityPool
Roles:
authenticated: !Ref CognitoIdentityAuthenticatedRole
unauthenticated: !Ref CognitoIdentityUnauthenticatedRole
#Output IDs and ARNs
Outputs:
CognitoUserPoolID:
Value:
Ref: CognitoUserPool
Export:
Name: !Sub "${AWS::StackName}-CognitoUserPoolID"
CognitoUserPoolClientID:
Value:
Ref: CognitoUserPoolClient
Export:
Name: !Sub "${AWS::StackName}-CognitoUserPoolClientID"
CognitoIdentityPoolID:
Value:
Ref: CognitoIdentityPool
Export:
Name: !Sub "${AWS::StackName}-CognitoIdentityPoolID"
I see a similar question posted but no answer was provided: Access to Role 'cognito role' is forbidden
I figured it out. The unauthenticated role needs the Arn and not the logical ID.
CognitoIdentityPoolRoleMapping:
Type: "AWS::Cognito::IdentityPoolRoleAttachment"
Properties:
IdentityPoolId: !Ref CognitoIdentityPool
Roles:
authenticated: !GetAtt CognitoIdentityAuthenticatedRole.Arn
unauthenticated: !GetAtt CognitoIdentityUnauthenticatedRole.Arn
I'm trying to create my cognito resources through cloudformation. Below template works just fine;
AWSTemplateFormatVersion: 2010-09-09
Resources:
CognitoAuthRole:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Federated: cognito-identity.amazonaws.com
Action:
- 'sts:AssumeRoleWithWebIdentity'
Condition:
StringEquals:
'cognito-identity.amazonaws.com:aud':
Ref: CognitoIdentityPool
'ForAnyValue:StringLike':
'cognito-identity.amazonaws.com:amr': authenticated
CognitoUserPool:
Type: 'AWS::Cognito::UserPool'
Properties:
UsernameAttributes:
- email
AutoVerifiedAttributes:
- email
CognitoUserPoolClient:
Type: 'AWS::Cognito::UserPoolClient'
Properties:
UserPoolId:
Ref: CognitoUserPool
ExplicitAuthFlows:
- ADMIN_NO_SRP_AUTH
GenerateSecret: false
CognitoIdentityPool:
Type: 'AWS::Cognito::IdentityPool'
Properties:
AllowUnauthenticatedIdentities: true
CognitoIdentityProviders:
- ClientId:
Ref: CognitoUserPoolClient
ProviderName:
'Fn::GetAtt':
- CognitoUserPool
- ProviderName
CognitoIdentityPoolRoles:
Type: 'AWS::Cognito::IdentityPoolRoleAttachment'
Properties:
IdentityPoolId:
Ref: CognitoIdentityPool
Roles:
authenticated:
'Fn::GetAtt':
- CognitoAuthRole
- Arn
But when I add RoleMappings attribute to CognitoIdentityPoolRoles resource, Cloudformation returns an error and can not create the stack. Modified resource is below;
CognitoIdentityPoolRoles:
Type: 'AWS::Cognito::IdentityPoolRoleAttachment'
Properties:
IdentityPoolId:
Ref: CognitoIdentityPool
Roles:
authenticated:
'Fn::GetAtt':
- CognitoAuthRole
- Arn
RoleMappings:
AmbiguousRoleResolution: Deny
Type: Rules
RulesConfiguration:
Rules:
- Claim: 'custom:role'
MatchType: Equals
Value: viewer
RoleARN:
'Fn::GetAtt':
- CognitoAuthRole
- Arn
- Claim: 'custom:role'
MatchType: Equals
Value: editor
RoleARN:
'Fn::GetAtt':
- CognitoAuthRole
- Arn
As you can see above RoleMappings type is Rules. You could try with Token parameter and the outcome doesn't change.
CognitoIdentityPoolRoles:
Type: 'AWS::Cognito::IdentityPoolRoleAttachment'
Properties:
IdentityPoolId:
Ref: CognitoIdentityPool
Roles:
authenticated:
'Fn::GetAtt':
- CognitoAuthRole
- Arn
RoleMappings:
AmbiguousRoleResolution: Deny
Type: Token
Unfortunately error message doesn't give any clue, I can not make any progress and stuck in this stage.
Status Type Logical ID Status Reason
CREATE_FAILED AWS::Cognito::IdentityPoolRoleAttachment CognitoIdentityPoolRoles Internal Failure
How can I make IdentityPoolRoleAttachment with RoleMappings work?
I've got the same issue, and unfortunately as i could see the RoleMappings are not supported yet into CloudFormation, so we ever will catch this 'Internal Failure'.
But there is some workarounds that you can do to solve your problem. In my case I've used the boto3 library to invoke IdentityPool updates inside a Lambda Function and I've used the Severless Framework, but the same purpose could be did with SAM or another CloudFormation stack framework.
So, I did these steps using 2 separated stacks:
Create First stack including all your Cognito Resources (UserPool, UserPoolClient, IdentityPool) and IamRoles that you will assign them and on the Outputs section, Export the necessary IDs and ARNs of your Resources to be used on the next stack.
service: cognito-template
provider:
name: aws
stage: dev
region: us-east-1
stackName: cognito-template-${self:provider.stage}-resources
custom:
system:
name: myapp
cognitoclientname: MyAppClient
resources:
Resources:
# ## ## ## ## ## ## ## ## ## ## ## ## ## Definicao de Usuários Cognito UserPool ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## #
UserPool:
Type: AWS::Cognito::UserPool
Properties:
UserPoolName: ${self:custom.system.name}userpool
AdminCreateUserConfig:
AllowAdminCreateUserOnly: True
UnusedAccountValidityDays: 30
EmailVerificationMessage: Clique no link abaixo para verificar seu endereço de e-mail. {####}
EmailVerificationSubject: Seu link de verificação
MfaConfiguration: OFF
Policies:
PasswordPolicy:
MinimumLength: 8
RequireLowercase: false
RequireNumbers: false
RequireSymbols: false
RequireUppercase: false
Schema:
- AttributeDataType: String
DeveloperOnlyAttribute: false
Mutable: true
Name: name
Required: true
- AttributeDataType: String
DeveloperOnlyAttribute: false
Mutable: true
Name: family_name
Required: true
- AttributeDataType: String
DeveloperOnlyAttribute: false
Mutable: true
Name: email
Required: true
- AttributeDataType: String
DeveloperOnlyAttribute: false
Mutable: true
Name: phone_number
Required: true
- AttributeDataType: String
DeveloperOnlyAttribute: false
Mutable: true
Name: gender
Required: true
- AttributeDataType: String
DeveloperOnlyAttribute: false
Mutable: true
Name: permission
Required: false
UsernameAttributes:
- email
- phone_number
# ## ## ## ## ## ## ## ## ## ## ## ## ## Client Cognito ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## #
AppUserPoolClient:
Type: AWS::Cognito::UserPoolClient
Properties:
ClientName: ${self:custom.system.cognitoclientname}
ExplicitAuthFlows:
- ADMIN_NO_SRP_AUTH
- USER_PASSWORD_AUTH
GenerateSecret: false
RefreshTokenValidity: 1
UserPoolId: !Ref UserPool
# ## ## ## ## ## ## ## ## ## ## ## ## ## Provedor de Identidade Cognito ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## #
AppIdentityPool:
Type: AWS::Cognito::IdentityPool
Properties:
IdentityPoolName: ${self:custom.system.name}identitypool
AllowUnauthenticatedIdentities: false
CognitoIdentityProviders:
- ClientId: !Ref AppUserPoolClient
ProviderName: !GetAtt UserPool.ProviderName
AppIdentitiesRolesAttachment:
Type: AWS::Cognito::IdentityPoolRoleAttachment
DependsOn:
- AppIdentityPool
- CognitoAuthorizedRole
- CognitoUnAuthorizedRole
Properties:
IdentityPoolId: !Ref AppIdentityPool
Roles:
authenticated: !GetAtt CognitoAuthorizedRole.Arn
unauthenticated: !GetAtt CognitoUnAuthorizedRole.Arn
CognitoAuthorizedRole:
Type: "AWS::IAM::Role"
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Federated: "cognito-identity.amazonaws.com"
Action:
- "sts:AssumeRoleWithWebIdentity"
Condition:
StringEquals:
"cognito-identity.amazonaws.com:aud": !Ref AppIdentityPool
"ForAnyValue:StringLike":
"cognito-identity.amazonaws.com:amr": authenticated
Policies:
- PolicyName: "CognitoAuthorizedPolicy"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Action:
- "mobileanalytics:PutEvents"
- "cognito-sync:*"
- "cognito-identity:*"
Resource: "*"
- Effect: "Allow"
Action:
- "lambda:InvokeFunction"
Resource: "*"
CognitoUnAuthorizedRole:
Type: "AWS::IAM::Role"
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Federated: "cognito-identity.amazonaws.com"
Action:
- "sts:AssumeRoleWithWebIdentity"
Condition:
StringEquals:
"cognito-identity.amazonaws.com:aud": !Ref AppIdentityPool
"ForAnyValue:StringLike":
"cognito-identity.amazonaws.com:amr": unauthenticated
Policies:
- PolicyName: "CognitoUnauthorizedPolicy"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Action:
- "mobileanalytics:PutEvents"
- "cognito-sync:*"
Resource: "*"
AdministradorRole:
Type: "AWS::IAM::Role"
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Federated: "cognito-identity.amazonaws.com"
Action:
- "sts:AssumeRoleWithWebIdentity"
Condition:
StringEquals:
"cognito-identity.amazonaws.com:aud": !Ref AppIdentityPool
"ForAnyValue:StringLike":
"cognito-identity.amazonaws.com:amr": authenticated
Policies:
- PolicyName: "CognitoAdministradorPolicy"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Action:
- "mobileanalytics:PutEvents"
- "cognito-sync:*"
Resource: "*"
GerenciadorRole:
Type: "AWS::IAM::Role"
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Federated: "cognito-identity.amazonaws.com"
Action:
- "sts:AssumeRoleWithWebIdentity"
Condition:
StringEquals:
"cognito-identity.amazonaws.com:aud": !Ref AppIdentityPool
"ForAnyValue:StringLike":
"cognito-identity.amazonaws.com:amr": authenticated
Policies:
- PolicyName: "CognitoAdministradorPolicy"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Action:
- "mobileanalytics:PutEvents"
- "cognito-sync:*"
Resource: "*"
- Effect: "Allow"
Action:
- "s3:GetObject"
- "s3:PutObject"
Resource:
- "arn:aws:s3:::${self:custom.system.name}/public/*"
# ## ## ## ## ## ## ## ## ## ## ## ## ## IAM Permission to lambda script execute update into IdentityPoolRoleMappings ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## #
MigrationScriptRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Service:
- lambda.amazonaws.com
Action:
- "sts:AssumeRole"
Policies:
- PolicyName: "MigrationScriptPolicy"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Action:
- "cognito-idp:*"
- "cognito-identity:*"
- "iam:*"
Resource: "*"
Outputs:
UserPoolId:
Value: !Ref UserPool
Export:
Name: "UserPool::Id"
UserPoolArn:
Value: !GetAtt UserPool.Arn
Export:
Name: "UserPool::Arn"
UserPoolClientId:
Value: !Ref AppUserPoolClient
Export:
Name: "AppUserPoolClient::Id"
AppIdentityPoolId:
Value: !Ref AppIdentityPool
Export:
Name: "AppIdentityPool::Id"
AdministradorRoleArn:
Value: !GetAtt AdministradorRole.Arn
Export:
Name: "AdministradorRole::Arn"
GerenciadorRoleArn:
Value: !GetAtt GerenciadorRole.Arn
Export:
Name: "GerenciadorRole::Arn"
MigrationScriptRoleArn:
Value: !GetAtt MigrationScriptRole.Arn
Export:
Name: "MigrationScriptRole::Arn"
Create second stack including the lambda function that will invoke update_user_pool from boto3 library. This function must receive the exported values of the first one stack and attached them into the enviroment variabels to be used when the function will invoke.
service: cognito-template
provider:
name: aws
stage: dev
region: us-east-1
stackName: cognito-template-${self:provider.stage}-functions
functions:
migration-script:
handler: lambda_function.handler
runtime: python3.6
role:
Fn::ImportValue: !Sub MigrationScriptRole::Arn
environment:
USER_POOL_REGION: us-east-1 # here you can change to you preferred region if you want
USER_POOL_ID:
Fn::ImportValue: !Sub UserPool::Id
USER_POOL_CLIENT_ID:
Fn::ImportValue: !Sub AppUserPoolClient::Id
IDENTITY_POOL_ID:
Fn::ImportValue: !Sub AppIdentityPool::Id
ADMINISTRADOR_ROLE_ARN:
Fn::ImportValue: !Sub AdministradorRole::Arn
GERENCIADOR_ROLE_ARN:
Fn::ImportValue: !Sub GerenciadorRole::Arn
Finally, the code of the lambda function to execute an update via boto3 call, for that, i've used the python3.6, but can use Node(must see the boto3 docs for Node)
import boto3
import os
def handler(event, context):
setup_cognito()
return event
def setup_cognito():
define_cognito_attributes()
create_cognito_identity_roles()
def create_cognito_identity_roles():
user_pool_region = os.environ['USER_POOL_REGION']
user_pool_id = os.environ['USER_POOL_ID']
user_pool_client_id = os.environ['USER_POOL_CLIENT_ID']
identity_pool_id = os.environ['IDENTITY_POOL_ID']
administrador_role = os.environ['ADMINISTRADOR_ROLE_ARN']
gerenciador_role = os.environ['GERENCIADOR_ROLE_ARN']
client_identity = boto3.client('cognito-identity')
client_idp = boto3.client('cognito-idp')
response = client_identity.get_identity_pool_roles(IdentityPoolId=identity_pool_id)
identity_provider = "cognito-idp.{}.amazonaws.com/{}:{}".format(user_pool_region, user_pool_id, user_pool_client_id)
options = {
'IdentityPoolId': response['IdentityPoolId'],
'Roles': response['Roles'],
'RoleMappings': {
identity_provider: {
'Type': 'Rules',
'AmbiguousRoleResolution': 'AuthenticatedRole',
'RulesConfiguration': {
'Rules': [
{
'Claim': 'custom:permission',
'MatchType': 'Equals',
'Value': 'ADMNISTRADOR',
'RoleARN': administrador_role
},
{
'Claim': 'custom:permission',
'MatchType': 'Equals',
'Value': 'GERENCIADOR',
'RoleARN': gerenciador_role
}
]
}
}
}
}
response = client_identity.set_identity_pool_roles(IdentityPoolId=options['IdentityPoolId'], Roles=options['Roles'], RoleMappings=options['RoleMappings'])
def define_cognito_attributes():
user_pool_id = os.environ['USER_POOL_ID']
user_pool_client_id = os.environ['USER_POOL_CLIENT_ID']
client = boto3.client('cognito-idp')
response = client.update_user_pool_client(
UserPoolId=user_pool_id,
ClientId=user_pool_client_id,
WriteAttributes=[
'custom:permission',
'phone_number',
'email',
'name',
'family_name',
'gender'
]
)
After create, the lambda function can be invoked by CLI or WEB 'Test'Button and then your role mappings will be assigned to you IdentityPool as you wish.
Hope it can help you! (Y)
I've created Cognito User Pool through AWS Console, but I want to automate creation of new Cognito User Pools through CloudFormation. Can I export my current User Pool configuration to CloudFormation template?
Its not possible to export. You would need the below 6 resources to automate the process.
Cognito Authenticated role
Cognito unAuthenticated role
User pool
User Pool Client
Identity Pool
Identity Pool Role attachment
You would need 3 outputs which you might need to use in your code. Below is the code for creating these
AWSTemplateFormatVersion: 2010-09-09
Parameters:
envParameter:
Type: String
Default: dev
AllowedValues: [ dev, test, qa, prod ]
Description: Suffix to be added for names.
Resources:
myApiUserPool:
Type: "AWS::Cognito::UserPool"
Properties:
UserPoolName: !Sub myApiUserPool${envParameter}
myApiUserPoolClient:
Type: "AWS::Cognito::UserPoolClient"
Properties:
ClientName: !Sub myApiUserPoolClient${envParameter},
GenerateSecret: False
RefreshTokenValidity: 30
UserPoolId: !Ref myApiUserPool
myApiIdentityPool:
Type: "AWS::Cognito::IdentityPool"
Properties:
IdentityPoolName: !Sub myApiIdentityPool${envParameter}
AllowUnauthenticatedIdentities: False
CognitoIdentityProviders:
- ClientId: !Ref myApiUserPoolClient
ProviderName: !GetAtt myApiUserPool.ProviderName
cognitoUnauthRole:
Type: 'AWS::IAM::Role'
Properties:
RoleName: !Sub Cognito_${myApiIdentityPool.Name}_Unauth_Role
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Federated: cognito-identity.amazonaws.com
Action: [ 'sts:AssumeRole' ]
Policies:
- PolicyName: cognitounauth
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- mobileanalytics:PutEvents
- cognito-sync:*
Resource:
- "*"
cognitoAuthRole:
Type: 'AWS::IAM::Role'
Properties:
RoleName: !Sub Cognito_${myApiIdentityPool.Name}_Auth_Role
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Federated: cognito-identity.amazonaws.com
Action: [ 'sts:AssumeRole' ]
Policies:
- PolicyName: cognitoauth
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- mobileanalytics:PutEvents
- cognito-sync:*
- execute-api:*
Resource:
- "*"
myApiIdentityPoolRoleAttachment:
DependsOn: [ myApiIdentityPool, cognitoUnauthRole, cognitoAuthRole ]
Type: "AWS::Cognito::IdentityPoolRoleAttachment"
Properties:
IdentityPoolId: !Ref myApiIdentityPool
Roles:
authenticated: !GetAtt cognitoAuthRole.Arn
unauthenticated: !GetAtt cognitoUnauthRole.Arn
Outputs:
userPool:
Description: "User pool ID"
Value: !Ref myApiUserPool
identityPool:
Description: "Identity pool ID"
Value: !Ref myApiIdentityPool
ClientId:
Description: "Client id for the user pool appclient"
Value: !Ref myApiUserPoolClient
It's not currently possible to export existing user pools from Cognito. You can, however, create new user pools in AWS CloudFormation and then manage those pools from CloudFormation itself going forward, using AWS::Cognito::UserPool resource type.
I am going to use the describe-user-pool action and then build the cf template based on the output