Resolved: Lambda deploy: The policy failed legacy parsing (Service: AmazonIdentityManagement

This post is about an error I encountered after upgrading to Serverless 2.28. My solution is provided, but it probably isn’t the best one.

node version: 14.16.0

package.json devDependencies:

“serverless”: “^2.28.7”,
“serverless-pseudo-parameters”: “^2.5.0”

The serverless file appears at the bottom of this post.

The Problem

serverless deploy resulted in:

An error occurred: IamRoleLambdaExecution - The policy failed legacy parsing (Service: AmazonIdentityManagement; Status Code: 400; Error Code: MalformedPolicyDocument;

A Solution

  1. Add the serverless-pseudo-parameters plugin. Despite the “warning” from “npm install serverless-pseudo-parameters”, this still seems necessary with version 2.28. I think this has something to do with #{AWS::AccountId}
  2. When using ${ , only reference fields under custom: instead of provider:. I have experienced glitches with references with older versions of Serverless. I can not explain them.

serverless.yml

frameworkVersion: '>=1.1.0'
service: ehr-download
plugins:
  - serverless-step-functions
  - serverless-pseudo-parameters
package:
  exclude:
    - package-lock.json
    - README.md
    - serverless.yml
    - docs/**
    - logs/**
    - node_modules/**/aws-sdk/**
    - node_modules/**/README.*
    - test/**
custom:
  stage: ${opt:stage, 'dev'}
  bucket: ${opt:bucket, '${self:custom.stage}'}
  region: ${opt:region, 'us-west-2'}
  database: ${opt:database, ''}
provider:
  name: aws
  stage: ${self:custom.stage}
  lambdaHashingVersion: 20201221
  runtime: nodejs14.x
  memorySize: 512
  timeout: 600
  region: ${self:custom.region}
  vpc:
    securityGroupIds: ${ssm:/terraform-output/${self:custom.stage}/vpc/security-groups/default/id/value~split}
    subnetIds: ${ssm:/terraform-output/${self:custom.stage}/vpc/subnets/private/ids/value~split}
  iam:
    role:
      statements:
        - Effect: Allow
          Action:
            - logs:CreateLogGroup
            - logs:CreateLogStream
            - logs:DescribeLogStreams
            - logs:PutLogEvents
          Resource:
            - arn:aws:logs:*:*:*
        - Effect: Allow
          Action:
            - s3:PutObject
            - s3:PutObjectAcl
          Resource:
            - arn:aws:s3:::${self:custom.bucket}/medicalRecord/*
        - Effect: Allow
          Action:
            - rds-db:connect
          Resource:
            - arn:aws:rds-db:${self:custom.region}:#{AWS::AccountId}:dbuser:${ssm:/terraform-output/${self:custom.stage}/rds/resource-id/value}/${self:service}
        - Effect: Allow
          Action:
            - ssm:GetParameter
          Resource:
            - arn:aws:ssm:${self:custom.region}:#{AWS::AccountId}:parameter/${self:custom.stage}/unity/ehr-api/config/.env
functions:
  ehr-download:
    name: ${self:service}-${self:custom.stage}
    handler: index.handler
    environment:
      NODE_OPTIONS: --tls-min-v1.0
      NODE_ENV: ${self:custom.stage}
      DATABASE_HOST: ${ssm:/terraform-output/${self:custom.stage}/rds/hostname/value}
      DATABASE_NAME: ${self:custom.database}
      S3_BUCKET: ${self:custom.bucket}
2 Likes

We just tried to replace #{AWS::AccountId} with ${AWS::AccountId} and are receiving the same errors still.

Specifically, our use case is in the following location:

provider:
  ...
  iamRoleStatements:
    - Action:
        - secretsmanager:GetSecretValue
      Effect: 'Allow'
      Resource: 'arn:aws:someservice:${AWS::Region}:${AWS::AccountId}:something:/*/*'

I upgraded our serverless version to 2.43.1

@mrowles and anyone else having issues with ${AWS::AccountId} in your template,

Add !Sub before the string and it works without issue. This will work with or without quotes around the string containing !Sub.

Using your example:

provider:
  ...
  iamRoleStatements:
    - Action:
        - secretsmanager:GetSecretValue
      Effect: 'Allow'
      Resource: !Sub 'arn:aws:someservice:${AWS::Region}:${AWS::AccountId}:something:/*/*'

Example, without quotes:

Resources:
  TestBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub ${self:app}-${self:service}-${AWS::AccountId}-twilio-results

Yep, I was meant to come back here and update that I missed those 4 little characters :slight_smile: Thanks mate.