amplify-cli icon indicating copy to clipboard operation
amplify-cli copied to clipboard

support `NotResource` in function's `custom-policies.json`

Open jamime opened this issue 2 years ago • 3 comments

Before opening, please confirm:

  • [X] I have installed the latest version of the Amplify CLI (see above), and confirmed that the issue still persists.
  • [X] I have searched for duplicate or closed issues.
  • [X] I have read the guide for submitting bug reports.
  • [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.

How did you install the Amplify CLI?

npm

If applicable, what version of Node.js are you using?

v16.14.0

Amplify CLI Version

7.6.22

What operating system are you using?

Mac

Did you make any manual changes to the cloud resources managed by Amplify? Please describe the changes made.

No manual changes made

Amplify Categories

function

Amplify Commands

push

Describe the bug

Unable to use NotResource in amplify/backend/function/authCreateAuthChallenge/custom-policies.json. I want to grant access to SNS publish to all mobile numbers, but not a SNS topic.

[
  {
    "Effect": "Allow",
    "Action": [
        "sns:Publish"
    ],
    "NotResource": "arn:aws:sns:*:*:*"
  }
]
Error: Invalid custom IAM policies in the authCreateAuthChallenge function.

    Edit <project-dir>/amplify/backend/function/authCreateAuthChallenge/custom-policies.json to fix
    Learn more about custom IAM policies for function: https://docs.amplify.aws/cli/function/#access-existing-aws-resource-from-lambda-function
should have required property 'Resource'

Expected behavior

amplify push function authCreateAuthChallenge should work with this policy file.

Reproduction steps

  1. amplify init
  2. amplify add function and name it authCreateAuthChallenge.
  3. Update amplify/backend/function/authCreateAuthChallenge/custom-policies.json to include
[
  {
    "Effect": "Allow",
    "Action": [
        "sns:Publish"
    ],
    "NotResource": "arn:aws:sns:*:*:*"
  }
]

GraphQL schema(s)

# Put schemas below this line


Log output

2022-02-28T12:02:46.963Z|info : amplify version core  {"version":true,"yes":false}
2022-02-28T12:04:45.446Z|info : amplify push function authCreateAuthChallenge 
2022-02-28T12:04:45.484Z|info : amplify-cli-core.banner-message/index.ts.fetch banner messages from https://aws-amplify.github.io/amplify-cli/banner-message.json({}
2022-02-28T12:05:49.703Z|info : amplify-provider-awscloudformation.system-config-manager.getProfileConfig(["[***]"])
2022-02-28T12:05:49.705Z|info : amplify-provider-awscloudformation.system-config-manager.getProfiledAwsConfig.profileConfig([{"region":"eu-west-2"}])
2022-02-28T12:05:49.705Z|info : amplify-provider-awscloudformation.system-config-manager.getProfileCredentials(["[***]"])
2022-02-28T12:05:49.928Z|info : amplify-provider-awscloudformation.aws-s3.uploadFile.s3.putObject([{"Key":"[***]ify-[***]fn-[***]ates/[***]th/[***]th-[***]ger-[***]mation-[***]e.json","Bucket":"[***]ify-[***]ing-[***]ev-[***]837-[***]ment"}])
2022-02-28T12:05:50.896Z|info : amplify-provider-awscloudformation.push-resources.packageResources.s3.uploadFile([{"Key":"[***]ify-[***]lds/[***]hChallenge-[***]6a536532-[***].zip"}])
2022-02-28T12:05:50.897Z|info : amplify-provider-awscloudformation.aws-s3.uploadFile.s3.putObject([{"Key":"[***]ify-[***]lds/[***]hChallenge-[***]6a536532-[***].zip","Bucket":"[***]ify-[***]ing-[***]ev-[***]837-[***]ment"}])
2022-02-28T12:05:51.248Z|error : amplify-provider-awscloudformation.push-resources.run([{"resourcesToBeCreated":[],"resourcesToBeUpdated":[{"build":true,"providerPlugin":"[***]rmation","service":"Lambda","lastBuildTimeStamp":"2022-02-28T12:05:50.861Z","lastBuildType":"PROD","lastPackageTimeStamp":"2022-02-28T12:01:43.941Z","distZipFilename":"[***]hChallenge-[***]6a536532-[***].zip","s3Bucket":{"deploymentBucketName":"[***]ify-[***]ing-[***]ev-[***]837-[***]ment","s3Key":"[***]ify-[***]lds/[***]hChallenge-[***]6a536532-[***].zip"},"providerMetadata":{"s3TemplateURL":"https://s3.amazonaws.com/[***]ify-[***]ing-[***]ev-[***]837-[***]ment/amplify-cfn-templates/function/[***]hChallenge-cloudformation-template.json","logicalId":"[***]AuthChallenge"},"lastPushTimeStamp":"2022-02-27T18:05:11.897Z","output":{"Region":"eu-west-2","Arn":"[***]mbda:eu-[***]st-[***]CreateAuthChallenge-[***]ev","Name":"[***]hChallenge-[***]ev","LambdaExecutionRole":"[***]hChallenge-[***]ev"},"lastPushDirHash":"[***]=","resourceName":"[***]hChallenge","category":"function"}],"resourcesToBeSynced":[],"resourcesToBeDeleted":[],"rootStackUpdated":false,"tagsUpdated":false,"allResources":[{"build":true,"providerPlugin":"[***]rmation","service":"Lambda","lastBuildTimeStamp":"2022-02-28T12:05:50.861Z","lastBuildType":"PROD","lastPackageTimeStamp":"2022-02-28T12:01:43.941Z","distZipFilename":"[***]hChallenge-[***]6a536532-[***].zip","s3Bucket":{"deploymentBucketName":"[***]","s3Key":"[***]ify-[***]lds/[***]hChallenge-[***]6a536532-[***].zip"},"providerMetadata":{"s3TemplateURL":"https://s3.amazonaws.com/[***]/amplify-cfn-templates/function/authCreateAuthChallenge-cloudformation-template.json","logicalId":"[***]AuthChallenge"},"lastPushTimeStamp":"2022-02-27T18:05:11.897Z","output":{"Region":"eu-west-2","Arn":"[***]mbda:eu-[***]st-[***]CreateAuthChallenge-[***]ev","Name":"authCreateAuthChallenge-dev","LambdaExecutionRole":"authCreateAuthChallenge-dev"},"lastPushDirHash":"/[***]=","resourceName":"authCreateAuthChallenge","category":"function"}]}])
Error: Invalid custom IAM policies in the authCreateAuthChallenge function.

    Edit <project-dir>/amplify/backend/function/authCreateAuthChallenge/custom-policies.json to fix
    Learn more about custom IAM policies for function: https://docs.amplify.aws/cli/function/#access-existing-aws-resource-from-lambda-function
should have required property 'Resource'

Additional information

I can set an inline policy using the same document via the AWS console.

jamime avatar Feb 28 '22 12:02 jamime

Hey @jamime :wave: thanks for raising this! Can you try to set NotResource's value to an array? https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_notresource.html

josefaidt avatar Feb 28 '22 22:02 josefaidt

Using an array gives the same error message.

should have required property 'Resource'

[
  {
    "Effect": "Allow",
    "Action": [
        "sns:Publish"
    ],
    "NotResource": ["arn:aws:sns:*:*:*"]
  }
]

jamime avatar Mar 29 '22 19:03 jamime

Hey @jamime thanks for the clarification! I will mark this as a feature request to support NotResource, however in the mean time can you see if mixing DENY/ALLOW policies will accomplish this?

[
  {
    "Effect": "Deny",
    "Action": ["sns:Publish"],
    "Resource": ["arn:aws:sns:*:*:*"]
  },
  {
    "Effect": "Allow",
    "Action": ["sns:Publish"],
    "Resource": ["*"]
  }
]

Using the following Lambda code we are able to send messages via SMS

import { SNSClient, PublishCommand } from '@aws-sdk/client-sns'
const client = new SNSClient()

/**
 * Publish a message to a phone number
 * @param {string} number - phone number of recipient
 * @param {string} [message] - message to send to phone number
 * @returns {import('@aws-sdk/client-sns').PublishCommandOutput}
 */
async function publish(number, message) {
  /** @type {import('@aws-sdk/client-sns').PublishCommandInput} */
  const input = {
    PhoneNumber: number || '+5555555555',
    Message: message || 'SMS from Lambda!',
  }

  /** @type {import('@aws-sdk/client-sns').PublishCommand} */
  const command = new PublishCommand(input)
  const response = await client.send(command)
  return response
}

/**
 * @type {import('@types/aws-lambda').APIGatewayProxyHandler}
 */
export async function handler(event) {
  const { number, message } = event?.body || {}
  const response = await publish(number, message)
  return {
    statusCode: 200,
    body: JSON.stringify(response),
  }
}

josefaidt avatar Mar 30 '22 16:03 josefaidt