We have the following code in an ECS Fargate container however it is constantly returning an error. When running identical code in a lambda with IAM authentication and the correct role setup, I am able to successfully run this.
Network error: Response not successful: Received status code 403
UnrecognizedClientException
The security token included in the request is invalid.
import 'isomorphic-fetch';
import AWSAppSyncClient, { AUTH_TYPE } from 'aws-appsync';
import AWS from 'aws-sdk';
// Setup variables for client
const graphqlEndpoint = process.env.GRAPHQL_ENDPOINT;
const awsRegion = process.env.AWS_DEFAULT_REGION;
const client = new AWSAppSyncClient({
url: graphqlEndpoint,
region: awsRegion,
auth: {
type: AUTH_TYPE.AWS_IAM,
credentials: AWS.config.credentials,
},
disableOffline: true,
})
TaskDefinition:
Type: "AWS::ECS::TaskDefinition"
Properties:
ContainerDefinitions:
- Ommitted
Cpu: !FindInMap [CpuMap, !Ref Cpu, Cpu]
ExecutionRoleArn: !GetAtt "TaskExecutionRole.Arn"
Family: !Ref "AWS::StackName"
Memory: !FindInMap [MemoryMap, !Ref Memory, Memory]
NetworkMode: awsvpc
RequiresCompatibilities: [FARGATE]
TaskRoleArn: !GetAtt "TaskRole.Arn"
TaskRole:
Type: "AWS::IAM::Role"
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: "ecs-tasks.amazonaws.com"
Action: "sts:AssumeRole"
ManagedPolicyArns:
- "arn:aws:iam::aws:policy/AWSAppSyncInvokeFullAccess" # Invoke Access for AppSync
I eventually discovered that this was a result of AppSyncClient not able to load the credentials in ECS correctly.
As per AWS Docs on IAM roles in ECS, credentials are loaded different to other AWS services. Instead of credentials being populated in env vars, the Amazon ECS agent instead populated the AWS_CONTAINER_CREDENTIALS_RELATIVE_URI
variable with a path to the credentials. I was able to successfully get AWSAppSyncClient
working with IAM
authenticaiton in an ECS
container by first loading the ECS
credentials manually and passing it to AWSAppSyncClient
. The below example worked.
// AWSAppSyncClient needs to be provided ECS IAM credentials explicitly
const credentials = new AWS.ECSCredentials({
httpOptions: { timeout: 50000 },
maxRetries: 10,
});
AWS.config.credentials = credentials;
// Setup AppSync Config
const AppSyncConfig = {
url: graphqlEndpoint,
region: awsRegion,
auth: {
type: AUTH_TYPE.AWS_IAM,
credentials: AWS.config.credentials,
},
disableOffline: true,
};