Closed kush-prof closed 1 week ago
Hey,👋 thanks for raising this! I'm going to transfer this over to our API repository for better assistance 🙂
Hi @kush-prof , it seems like your schema and Lambda are configured correctly to have access to mutations. However, the default auth mode on your API is userPool
, as seen in defineData
. I can't see that in your Lambda you are setting the client's authMode to identityPool
so that it uses an IAM role to sign the request.
This page might be helpful:
This section in particular:
In the handler file for your function, configure the Amplify data client
// amplify/functions/data-access.ts import { Amplify } from 'aws-amplify'; import { generateClient } from 'aws-amplify/data'; import { Schema } from '../data/resource'; import { env } from '$amplify/env/<function-name>'; // replace with your function name Amplify.configure( { API: { GraphQL: { endpoint: env.<amplifyData>_GRAPHQL_ENDPOINT, // replace with your defineData name region: env.AWS_REGION, defaultAuthMode: 'identityPool' // required for request to be signed with IAM role for Lambda } } }, {
Hey @chrisbonifacio thanks for the response.
Sorry for missing that part in the initial report. Here is the snippet from handler.ts
import type { Handler } from 'aws-lambda';
import axios from 'axios';
import { RadarMatchSummaryResponse, ScheduleMatchesResponse } from '../types/types';
const API_KEY = process.env.RADAR_API_KEY;
const BASE_URL = 'https://api.sportradar.com/cricket-t2/en';
import { Amplify } from 'aws-amplify';
import { generateClient } from 'aws-amplify/data';
import { data, Schema } from '../../data/resource';
import { env } from '$amplify/env/ingest-radar-matches'; // replace with your function name
Amplify.configure(
{
API: {
GraphQL: {
endpoint: env.AMPLIFY_DATA_GRAPHQL_ENDPOINT, // replace with your defineData name
region: env.AWS_REGION,
defaultAuthMode: 'identityPool',
}
}
},
{
Auth: {
credentialsProvider: {
getCredentialsAndIdentityId: async () => ({
credentials: {
accessKeyId: env.AWS_ACCESS_KEY_ID,
secretAccessKey: env.AWS_SECRET_ACCESS_KEY,
sessionToken: env.AWS_SESSION_TOKEN,
},
}),
clearCredentialsAndIdentityId: () => {
/* noop */
},
},
},
}
);
const dataClient = generateClient<Schema>();
Still facing same error.
@chrisbonifacio I would like to emphasise on the point that I do not see the @aws_iam
decorator on the custom created mutation in the AppSync schema on AWS console. When I manually put that in the schema and save it. The function starts to work properly that tells me that the custom created mutation does not allow the IAM access to it and only the cognito user pool access as it has @aws_cognito_user_pools
@kush-prof I was able to solve this for function handler by attaching the apiRestPolicy to an IAM user like this
// create a new API stack
const apiStack = backend.createStack("api-stack");
const restApiName = "myRestApi";
// create a new REST API
const myRestApi = new RestApi(apiStack, restApiName, {
restApiName: "myRestApi",
deploy: true,
deployOptions: {
stageName: "dev",
},
defaultCorsPreflightOptions: {
allowOrigins: Cors.ALL_ORIGINS, // Restrict this to domains you trust
allowMethods: Cors.ALL_METHODS, // Specify only the methods you need to allow
allowHeaders: Cors.DEFAULT_HEADERS, // Specify only the headers you need to allow
},
});
// create a new Lambda integration
const lambdaIntegration = new LambdaIntegration(
backend.myApiFunction.resources.lambda
);
// create a new resource path with IAM authorization
const routePath = myRestApi.root.addResource("todos", {
defaultMethodOptions: {
authorizationType: AuthorizationType.IAM,
},
});
// add methods you would like to create to the resource path
routePath.addMethod("GET", lambdaIntegration);
routePath.addMethod("POST", lambdaIntegration);
routePath.addMethod("DELETE", lambdaIntegration);
routePath.addMethod("PUT", lambdaIntegration);
// add a proxy resource path to the API
ticketsPath.addProxy({
anyMethod: true,
defaultIntegration: lambdaIntegration,
});
// create a new IAM policy to allow Invoke access to the API
const apiRestPolicy = new Policy(apiStack, `RestApiPolicy`, {
statements: [
new PolicyStatement({
actions: ["execute-api:Invoke"],
resources: [
`${myRestApi.arnForExecuteApi("*", `/${todos}`, "dev")}`,
`${myRestApi.arnForExecuteApi("*", `/${todos}/*`, "dev")}`,
],
}),
],
});
const devApiConsumer = User.fromUserName(
apiStack,
"your-iam-user-name",
"your-iam-user-name"
);
const users = [devApiConsumer];
users.forEach((user) => {
user.attachInlinePolicy(apiRestPolicy);
});
// add outputs to the configuration file
backend.addOutput({
custom: {
API: {
[myRestApi.restApiName]: {
endpoint: myRestApi.url,
region: Stack.of(myRestApi).region,
apiName: myRestApi.restApiName,
},
},
},
});
@Sterv thanks for the reply but I don' think that your solution fits my exact usecase.
@chrisbonifacio I was wondering if we have a more elegant solution or is it a bug in amplify or simply am I missing something?
Hi @kush-prof, apologies for the delay. We still need to try and reproduce the issue.
Unless I'm mistaken, I don't think that the schema necessarily needs to have @aws_iam for the Lambda to have access as long as IAM is an auth mode on the API.
If the Lambda's execution role has permissions to execute Queries & Mutations, I think that should be enough. Maybe the permissions are not being added to the role policy correctly.
Can you check the Lambda's execution role and confirm if it allows GraphQL queries/mutations on your API?
If not, then this is probably a bug and in the meantime you can try using my function.addToRolePolicy
to grant your Lambda permissions in the backend.ts file
Also, I noticed that your auth rule is allow.resources(ingest)
but what you're importing is ingestRadarMatches
. Seems like a typo or maybe you changed something after copy/pasting?
Secondly, looking at the schema again, you don't seem to have an auth rule that suggests IAM is an auth mode on the API. You only have allow.authenticated() and allow.resource. The identityPool
auth mode is facilitated by allow.guest()
, or allow.authenticated("identityPool")
this is what puts @aws_iam
directive in the schema.
@chrisbonifacio adding allow.authenticated("identityPool")
is adding @aws_iam
to the schema however it is not supported if we are writing custom functions. Getting the following error:
identityPool-based auth (allow.guest() and allow.authenticated('identityPool')) is not supported with a.handler.custom
Caused By: identityPool-based auth (allow.guest() and allow.authenticated('identityPool')) is not supported with a.handler.custom
Resolution: Check your data schema definition for syntax and type errors.
Is there any workaround for it or we will just simply have to use lambda functions here. Ideally I would want to use the custom js resolver here rather than a lambda function serving as a resolver for AppSync, I think it holds some benefits (maybe I'm wrong!).
So the idea is to create a custom mutation and get it triggered by a scheduler to do some operation on DynamoDB tables, since we cannot get the table names in the scheduler lambda directly (would've preferred this over anything else) I need to trigger a custom mutation, now since custom mutation with IAM permission do not allow custom js resolver in the lambda function attached to the mutation we will have to do a graphql mutation itself.
Let me know if you need more clarification.
Hi @kush-prof, the only difference I can tell between my reproduction app and the details in this issue is our @aws-amplify/backend
and @aws-amplify/backend-cli
versions. Could you make sure you are using the latest versions of those packages?
You might also have to update transitive dependencies like @aws-amplify/data-schema
. You can do so by running:
npm update @aws-amplify/data-schema
Hi 👋 Closing this as we have not heard back from you. If you are still experiencing this issue and in need of assistance, please feel free to comment and provide us with any information previously requested by our team members so we can re-open this issue and be better able to assist you.
Thank you!
This issue is now closed. Comments on closed issues are hard for our team to see. If you need more assistance, please open a new issue that references this one.
Environment information
Description
I have to write a scheduler lambda that should invoke my custom mutation on AppSync APIs but it seems I am unable to get it authorised to use the custom mutation. In the schema of AppSync on console I cannot see the directive @aws_iam on the custom mutation that I created and on the other hand it is present on all the out of box mutation and queires, this is preventing my lambda to access the custom mutations.
amplify/data/resource.ts
/createMatches.js
functions/ingest/handler.ts
The ingest function is a scheduler that needs to invoke
createMatch
mutation. I get the following error:This is because in the schema of AppSync
@aws_iam
is not present in the above custom mutation while is present of auto generated mutations and queries