Access denied error when Greengrass v2 component loads ML model from S3

Our Greengrass v2 component is failing to load an ML model from S3 during initialization. The component recipe specifies the model as an artifact, but we’re getting access denied errors:


AccessDenied: Access Denied when calling GetObject
at S3Client.getObject(S3Client.java:156)
Model URI: s3://ml-models-prod/anomaly-detection/model.tar.gz

The Greengrass core device has a token exchange role attached with these policies:

  • GreengrassV2TokenExchangeRoleAccess (AWS managed)
  • Custom policy with s3:GetObject on arn:aws:s3:::ml-models-prod/*

The S3 bucket has default encryption enabled and no bucket policy. The IAM policy simulator shows the permissions should work, but the component still can’t access the model. We’ve verified the bucket and object exist, and the model path in the recipe is correct.

What are we missing in the permission chain for Greengrass components to download ML model artifacts from S3?

Good catch on the KMS encryption. The bucket does use KMS with a custom key. I added kms:Decrypt to the token exchange role, but still getting the same error. The trust relationship looks correct with greengrass.amazonaws.com as the principal. Could there be an issue with how the component is requesting the artifact?

The policy simulator can be misleading for Greengrass because it doesn’t account for the STS assume role session policies. When Greengrass assumes your token exchange role, it applies additional session policies that might restrict S3 access. Try adding s3:ListBucket permission on the bucket ARN (not just the objects). Greengrass sometimes needs to list the bucket to verify object existence before download.

I’ll address all three focus areas systematically:

Greengrass IAM Execution Role: Your token exchange role needs multiple permissions beyond basic S3 access. Update the IAM policy:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::ml-models-prod",
        "arn:aws:s3:::ml-models-prod/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "kms:Decrypt",
        "kms:DescribeKey"
      ],
      "Resource": "arn:aws:kms:region:account:key/your-key-id"
    }
  ]
}

The ListBucket permission on the bucket itself (not just objects) is critical for Greengrass to verify artifact existence.

S3 Bucket/Object Permissions: The issue is likely a combination of IAM and KMS key policies. Your KMS key policy must explicitly allow the token exchange role:

{
  "Sid": "Allow Greengrass to decrypt model artifacts",
  "Effect": "Allow",
  "Principal": {
    "AWS": "arn:aws:iam::account:role/GGv2TokenExchangeRole"
  },
  "Action": [
    "kms:Decrypt",
    "kms:DescribeKey"
  ],
  "Resource": "*"
}

Additionally, if your S3 bucket has a bucket policy, ensure it doesn’t deny access to the Greengrass service or your role. Remove any explicit deny statements that might override the IAM permissions.

Policy Simulator Usage: The policy simulator has limitations with Greengrass because it doesn’t fully simulate the STS session policies applied during role assumption. Instead, test permissions using AWS CLI with the --debug flag:

# Pseudocode - Testing permission chain:
# 1. Assume the token exchange role using STS
# 2. Use temporary credentials to attempt S3 GetObject
# 3. Verify KMS decrypt operation succeeds
# 4. Check CloudTrail logs for denied API calls
# 5. Review Greengrass component logs for detailed error context

CloudTrail is your best tool here - it will show the exact principal and policy that denied the request.

One final check: ensure your Greengrass core device’s system time is synchronized. Certificate-based authentication can fail if there’s significant clock drift, causing access denied errors that appear to be permission-related.

After implementing these IAM policy updates and KMS key policy changes, restart your Greengrass core device to force re-authentication with the updated permissions. The component should then successfully download and load the ML model from S3.