amplify-category-api
amplify-category-api copied to clipboard
{ errorType: 'UnauthorizedException', message: 'Permission denied' } when calling mutation from GitHub action
How did you install the Amplify CLI?
No response
If applicable, what version of Node.js are you using?
16
Amplify CLI Version
12.10.1
What operating system are you using?
linux
Did you make any manual changes to the cloud resources managed by Amplify? Please describe the changes made.
No manual changes made
Describe the bug
I have a mutation query in my schema:
registerTenant(name: String, emailAddress: String, tenantName: String): Tenant @function(name: "plateletAddNewTenant-${env}") @auth(rules: [{allow: private, provider: iam}])
that I want to be able to call from a GitHub action. So far I've been able to set up permissions that allow the IAM account to call that mutation, but I'm getting this error:
{ errorType: 'UnauthorizedException', message: 'Permission denied' }
This is the policy I'm using for AppSync:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"appsync:GraphQL"
],
"Resource": [
"arn:aws:appsync:*:<id>:apis/*/types/Query/fields/getTenantByTenantName",
"arn:aws:appsync:*:<id>:apis/*/types/Mutation/resolvers/registerTenant"
]
}
]
}
It seems like it can call the getTenantByTenantName query fine, but gets that error on the registerTenant call.
in amplify/backend/api/platelet/custom-roles.json I have the following (with my proper id):
{
"adminRoleNames": [
"arn:aws:iam::<id>:user/test-test.bloodbikes.cloud"
]
}
I use this on another API I have and get no issue when making calls to it using IAM.
I tested running the action with a full admin access policy attached to the IAM user but it was still denied, so it seems like the API is returning that permission denied error rather than it being a problem with the policy.
It's strange that no error is returned when using getTenantByTenantName, which is just a queryField added to an index, but the registerTenant which is a custom function throws that error.
type Tenant
@auth(rules: [
{allow: private, operations: [read]},
{allow: private, provider: iam, operations: [read]},
])
@model {
id: ID!
name: String! @index(name: "byTenantName", queryField: "getTenantByTenantName")
referenceIdentifier: String!
admin: User! @hasOne
}
Expected behavior
I expect the query to complete without a permission denied error.
Reproduction steps
- Add a custom mutation to type Mutation with lambda function.
- Create access keys and set IAM policy to allow running that mutation.
- Set up GitHub action that calls the mutation.
This is the code I use in the GitHub action:
import * as core from "@actions/core";
import { Sha256 } from "@aws-crypto/sha256-js";
import { SignatureV4 } from "@aws-sdk/signature-v4";
import { HttpRequest } from "@aws-sdk/protocol-http";
import fetch, { Request } from "node-fetch";
import {
RegisterTenantMutationVariables,
GetTenantByTenantNameQueryVariables,
} from "./API";
import { registerTenant } from "./graphql/mutations";
import { getTenantByTenantName } from "./graphql/queries";
const request = async (queryDetails: { variables: any; query: string }) => {
const apiURL = core.getInput("tenantApiUrl");
const region = core.getInput("awsRegion");
const accessKeyId = core.getInput("awsAccessKeyId");
const secretAccessKey = core.getInput("awsSecretAccessKey");
console.log("apiURL", apiURL);
console.log("region", region);
console.log("queryDetails", queryDetails);
const endpoint = new URL(apiURL);
const credentials = {
accessKeyId,
secretAccessKey,
};
const signer = new SignatureV4({
credentials,
region,
service: "appsync",
sha256: Sha256,
});
const requestToBeSigned = new HttpRequest({
method: "POST",
headers: {
"Content-Type": "application/json",
host: endpoint.host,
},
hostname: endpoint.host,
body: JSON.stringify(queryDetails),
path: endpoint.pathname,
});
const signed = await signer.sign(requestToBeSigned);
const request = new Request(endpoint, signed);
return await fetch(request);
};
const errorCheck = (body: any) => {
if (body?.errors) {
console.error(body?.errors);
throw new Error(body?.errors[0].message);
}
};
export const registerTenantQuery = async (
input: RegisterTenantMutationVariables
) => {
const response = await request({
variables: input,
query: registerTenant,
});
const body = await response.json();
errorCheck(body);
return body?.data?.registerTenant;
};
export const getTenantByName = async (
variables: GetTenantByTenantNameQueryVariables
) => {
const response = await request({
variables,
query: getTenantByTenantName,
});
const body = await response.json();
errorCheck(body);
console.log("aaaa: ", body?.data?.getTenantByTenantName?.items);
return body?.data?.getTenantByTenantName?.items[0] || null;
};
Project Identifier
f97b80f7ee5ceef2a72f107f35e6d453
Log output
# Put your logs below this line
Additional information
No response
Before submitting, please confirm:
- [X] I have done my best to include a minimal, self-contained set of instructions for consistently reproducing the issue.
- [X] I have removed any sensitive information from my code snippets and submission.
Heyπ thanks for raising this! I'm going to transfer this over to our API repository for better assistance π
Why are you defining a separate policy when you define the Auth rules with the Auth directive @auth in the mutation declaration?
@biller-aivy the policy is for my IAM user that I use with GitHub actions. I want to be able to call that mutation from that user.
If I don't add any policy, I get a different kind of unauthorized error.
Hi @duckbytes,
I see you're declaring your IAM policy resource with resolvers in the registerTenant clause:
"arn:aws:appsync:*:<id>:apis/*/types/Mutation/resolvers/registerTenant"
I believe that should be fields:
"arn:aws:appsync:*:<id>:apis/*/types/Mutation/fields/registerTenant"
Please see AWS AppSync documentation for supported resource types.
Hope this helps.
hi @palpatim
I gave it a try with this policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"appsync:GraphQL"
],
"Resource": [
"arn:aws:appsync:*:<id>:apis/*/types/Query/fields/getTenantByTenantName/*",
"arn:aws:appsync:*:<id>:apis/*/types/Mutation/fields/registerTenant/*",
"arn:aws:appsync:*:<id>:apis/*/types/Query/fields/getTenantByTenantName",
"arn:aws:appsync:*:<id>:apis/*/types/Mutation/fields/registerTenant"
]
}
]
}
but I get the same permission denied error:
message: 'Not Authorized to access getTenantByTenantName on type Query'
The error is actually on the query and not the registerTenant mutation. I haven't been able to try if registerTenant works yet.
Hi @duckbytes, you've mentioned earlier that:
It's strange that no error is returned when using getTenantByTenantName, which is just a queryField added to an index, but the registerTenant which is a custom function throws that error.
And from the latest error message you've shared i.e Not Authorized to access getTenantByTenantName on type Query this seems to now be broken after adding those additional policies?
I don't see anything in those policies that could've caused this. Can you clarify which of the query or mutation is not working?
Hey π , This issue is being closed due to inactivity. If you are still experiencing the same problem and need further assistance, please feel free to leave a comment. This will enable us to reopen the issue and provide you with the necessary support.
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.