Skip to main content

AWS AppSync API has field-level logging set to ALL or ERROR

Overview

This check verifies that your AWS AppSync GraphQL APIs have field-level logging enabled. Field-level logging captures detailed information about each resolver execution, helping you monitor API activity, troubleshoot issues, and maintain an audit trail.

AppSync supports several log levels:

  • NONE - No logging (fails this check)
  • ERROR - Logs only resolver errors (passes this check)
  • INFO - Logs errors plus informational messages
  • DEBUG - Detailed debugging information
  • ALL - Complete logging of all field resolutions (passes this check)

Risk

Without field-level logging enabled:

  • No audit trail - You cannot track who accessed or modified data through your GraphQL API
  • Blind to attacks - Data exfiltration or tampering attempts go undetected
  • Slower incident response - When issues occur, you lack the traces needed for root-cause analysis
  • Compliance gaps - Many frameworks (PCI, SOC2, ISO27001) require logging for audit purposes

Remediation Steps

Prerequisites

You need:

  • AWS Console access with permissions to modify AppSync APIs
  • An IAM role that allows AppSync to write to CloudWatch Logs (the console can create this for you)
Required IAM permissions

To enable logging, your IAM user or role needs these permissions:

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"appsync:GetGraphqlApi",
"appsync:UpdateGraphqlApi"
],
"Resource": "arn:aws:appsync:*:*:apis/*"
},
{
"Effect": "Allow",
"Action": [
"iam:PassRole"
],
"Resource": "arn:aws:iam::*:role/*appsync*",
"Condition": {
"StringEquals": {
"iam:PassedToService": "appsync.amazonaws.com"
}
}
}
]
}

AWS Console Method

  1. Open the AWS AppSync console
  2. Select your GraphQL API from the list
  3. In the left navigation, click Settings
  4. Scroll to the Logging section
  5. Toggle Enable Logs to on
  6. For Field resolver log level, select Error (recommended) or All
  7. For the IAM role:
    • Select an existing role with CloudWatch Logs permissions, OR
    • Choose Create new role to let AWS create one automatically
  8. (Optional) Check Exclude verbose content to avoid logging sensitive request/response data
  9. Click Save
AWS CLI

First, ensure you have an IAM role that AppSync can assume to write logs. If you need to create one:

# Create the trust policy file
cat > /tmp/trust-policy.json << 'EOF'
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "appsync.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF

# Create the IAM role
aws iam create-role \
--role-name AppSyncLoggingRole \
--assume-role-policy-document file:///tmp/trust-policy.json \
--region us-east-1

# Attach the managed policy for CloudWatch Logs access
aws iam attach-role-policy \
--role-name AppSyncLoggingRole \
--policy-arn arn:aws:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs \
--region us-east-1

Then enable field-level logging on your AppSync API:

# Get your current API configuration
aws appsync get-graphql-api \
--api-id <your-api-id> \
--region us-east-1

# Update the API with logging enabled
aws appsync update-graphql-api \
--api-id <your-api-id> \
--name <your-api-name> \
--authentication-type <your-auth-type> \
--log-config fieldLogLevel=ERROR,cloudWatchLogsRoleArn=arn:aws:iam::<account-id>:role/AppSyncLoggingRole,excludeVerboseContent=true \
--region us-east-1

Replace the placeholders:

  • <your-api-id> - Your AppSync API ID (e.g., abc123xyz)
  • <your-api-name> - The name of your API
  • <your-auth-type> - Your authentication type (e.g., API_KEY, AWS_IAM, AMAZON_COGNITO_USER_POOLS)
  • <account-id> - Your AWS account ID
CloudFormation

This template creates an AppSync GraphQL API with field-level logging enabled and the required IAM role:

AWSTemplateFormatVersion: '2010-09-09'
Description: AWS AppSync GraphQL API with field-level logging enabled

Parameters:
ApiName:
Type: String
Description: Name of the AppSync GraphQL API
Default: MyGraphQLApi

Resources:
AppSyncLoggingRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub '${ApiName}-appsync-logging-role'
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: appsync.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs

AppSyncGraphQLApi:
Type: AWS::AppSync::GraphQLApi
Properties:
Name: !Ref ApiName
AuthenticationType: API_KEY
LogConfig:
CloudWatchLogsRoleArn: !GetAtt AppSyncLoggingRole.Arn
FieldLogLevel: ERROR
ExcludeVerboseContent: true

Outputs:
GraphQLApiId:
Description: AppSync GraphQL API ID
Value: !GetAtt AppSyncGraphQLApi.ApiId
GraphQLApiUrl:
Description: AppSync GraphQL API URL
Value: !GetAtt AppSyncGraphQLApi.GraphQLUrl

To add logging to an existing API, update your CloudFormation stack to include the LogConfig property.

Terraform
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}

provider "aws" {
region = "us-east-1"
}

variable "api_name" {
description = "Name of the AppSync GraphQL API"
type = string
default = "MyGraphQLApi"
}

# IAM role for AppSync to write to CloudWatch Logs
resource "aws_iam_role" "appsync_logging" {
name = "${var.api_name}-appsync-logging-role"

assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = {
Service = "appsync.amazonaws.com"
}
Action = "sts:AssumeRole"
}
]
})
}

resource "aws_iam_role_policy_attachment" "appsync_logging" {
role = aws_iam_role.appsync_logging.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs"
}

# AppSync GraphQL API with field-level logging
resource "aws_appsync_graphql_api" "example" {
name = var.api_name
authentication_type = "API_KEY"

log_config {
cloudwatch_logs_role_arn = aws_iam_role.appsync_logging.arn
field_log_level = "ERROR"
exclude_verbose_content = true
}
}

output "api_id" {
description = "AppSync GraphQL API ID"
value = aws_appsync_graphql_api.example.id
}

output "api_url" {
description = "AppSync GraphQL API URL"
value = aws_appsync_graphql_api.example.uris["GRAPHQL"]
}

To add logging to an existing AppSync API, add the log_config block to your aws_appsync_graphql_api resource.

Verification

After enabling logging, verify the configuration:

  1. In the AppSync console, go to your API and click Settings

  2. Confirm the Logging section shows:

    • Enable Logs: On
    • Field resolver log level: Error or All
    • A valid IAM role is selected
  3. Test that logs are flowing:

    • Run a GraphQL query against your API
    • Open CloudWatch Logs
    • Look for a log group named /aws/appsync/apis/<your-api-id>
    • Verify recent log entries appear
CLI verification commands
# Check current logging configuration
aws appsync get-graphql-api \
--api-id <your-api-id> \
--query 'graphqlApi.logConfig' \
--region us-east-1

# Expected output for a compliant API:
# {
# "fieldLogLevel": "ERROR",
# "cloudWatchLogsRoleArn": "arn:aws:iam::123456789012:role/...",
# "excludeVerboseContent": true
# }

# Verify logs are being written (after running a query)
aws logs describe-log-streams \
--log-group-name /aws/appsync/apis/<your-api-id> \
--order-by LastEventTime \
--descending \
--limit 5 \
--region us-east-1

Additional Resources

Notes

  • Cost considerations: Field-level logging generates CloudWatch Logs charges. Use ERROR level for production to balance visibility and cost. Only enable ALL or DEBUG temporarily for troubleshooting.

  • Sensitive data: Enable Exclude verbose content to prevent request/response mapping templates from appearing in logs, which could contain sensitive information.

  • Log retention: CloudWatch Logs are retained indefinitely by default. Set a retention policy on the /aws/appsync/apis/<api-id> log group to manage storage costs and comply with data retention requirements.

  • Multiple authentication types: When updating via CLI, you must specify the --authentication-type parameter. If your API uses multiple authentication providers, also include the --additional-authentication-providers parameter to preserve them.