Reputation: 4089
I want to invoke mutations on my AppSync API from Lambda functions in response to external events. Now I have been able to do this if I set AppSync to use IAM authorization and then provide access in the role of my Lambda function. The problem is that I need to use Cognito authorization because I need access to Cognito usernames in many of my resolver templates and I do not know of any way to do this when using IAM authorization.
I would thus like to know if there is any way I can authorise a Lambda function using Cognito User Pools to call my AppSync endpoint. Obviously I can create a dummy user in my pool and simply log in with it in the Lambda but Cognito User Pool logins are a very slow process and this method just sounds wrong anyway. The mutations I want to call from Lambdas don't need any Cognito info anyway.
What would also solve my problem is if I had a way to access the Cognito username in resolver templates when using IAM authorization.
Upvotes: 3
Views: 1328
Reputation: 5775
With user pools as your authentication mechanism, there is no way to get tokens to authorize with AWS AppSync without signing in, at some point. With that said, you could mitigate the overhead of that a bit. Ultimately, it boils down to what you suggested in your question, using a 'fake user'. It's not an uncommon solution, and involves having some admin level user, the credentials for whom would only be accessed from this Lambda.
First of all, I would recommend you not use the traditional SRP login, for latency reasons. One alternative would be to use AdminInitiateAuth/ADMIN_NO_SRP_AUTH, to offload the overhead of SRP calculations from your Lambda to the Cognito back end, with ADMIN_NO_SRP_AUTH turned on in your pool. I saw from your other question (Authenticate AppSync request with adminInitiateAuth) that you were thinking of doing this, however it is important to point out this is simply a different API used to sign a user in. You can read more about it here: https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-authentication-flow.html#amazon-cognito-user-pools-server-side-authentication-flow
An additional alternative could be a custom authentication flow. The same link above has more details on how to do this, but in short, you could set up a quicker flow that fits whatever specific needs your add has.
To improve overhead a bit more, you could then keep those tokens cached, to some degree. That could just mean keeping it in memory in the Lambda and checking their validity/expiry before using them, or even attaching a remote caching mechanism.
Upvotes: 2
Reputation: 5379
@Gerharddc, what if do you try to add policies that allow unauthenticated access to your Cognito Identity Pool?
I have this piece of code that defines authenticated and unauthenticated access to my Identity Pool (you can check the full code here in my personal project).
IdentityPoolUnauthorizedIAMRole:
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: unauthenticated
Policies:
- PolicyName: CognitoUserSignInUnauthorizedPolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- mobileanalytics:PutEvents
- mobiletargeting:PutEvents
- cognito-sync:*
- cognito-identity:*
Resource: '*'
IdentityPoolAuthorizedIAMRole:
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
Policies:
- PolicyName: CognitoUserSignInAuthorizedPolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- mobileanalytics:PutEvents
- mobiletargeting:PutEvents
- cognito-sync:*
- cognito-identity:*
Resource: '*'
# Assigns the roles to the Identity Pool
CognitoIdentityPoolRoleAttachment:
Type: AWS::Cognito::IdentityPoolRoleAttachment
Properties:
IdentityPoolId: !Ref CognitoIdentityPool
Roles:
unauthenticated: !GetAtt IdentityPoolUnauthorizedIAMRole.Arn
authenticated: !GetAtt IdentityPoolAuthorizedIAMRole.Arn
When I declare my AWS AppSync template, I add this template that permits users to access my AppSync endpoint when signed in:
AppSyncIAMPolicy:
Type: AWS::IAM::Policy
Description: Allow user consume AppSync when signed in
DependsOn: AppSyncGraphQLApi
Properties:
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- appsync:GraphQL
Resource:
- !Join ['/', [!GetAtt AppSyncGraphQLApi.Arn, '*']]
PolicyName: !Sub ${StackName}-appsync-iam-policy
Roles:
- !Sub ${IdentityPoolAuthorizedIAMRoleRef}
My point is: you can attach a policy that allows users not signed
(unauthenticated) access AppSync. Instead - !Sub ${IdentityPoolAuthorizedIAMRoleRef}
you can in the template above, you can try - !Sub ${IdentityPoolUnauthorizedIAMRoleRef}
.
Of course, you can specify which endpoints you allow unauthenticated access, for example:
AppSyncIAMPolicy:
Type: AWS::IAM::Policy
Description: Allow user consume AppSync when NOT signed in
DependsOn: AppSyncGraphQLApi
Properties:
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- appsync:GraphQL
Resource:
- arn:aws:appsync:us-west-2:123456789012:apis/YourGraphQLApiId/types/Query/fields/<Field-1>
- arn:aws:appsync:us-west-2:123456789012:apis/YourGraphQLApiId/types/Query/fields/<Field-2>
PolicyName: !Sub ${StackName}-appsync-iam-policy-unauthenticated
Roles:
- !Sub ${IdentityPoolUnauthorizedIAMRoleRef}
Upvotes: 0