2
votes

I am using the serverless framework to make a simple lambda based schema validation service with node.js and ajv library.

As stated here my local invocations work, however when I invoke remotely I get an access denied from S3. Furthermore when I run the policy simulation on aws with my specific resource, it indicates that the access is granted and now I am confused.

I invoke my function remotely with

SLS_DEBUG=* sls invoke -f validate --data '{"schema":"valid", "schema_version":""}'

The relevant error message I get back is:

platform-sdk fetching: POST https://api.serverless.com/core/tenants/l1nxit/applications/api/profileValue
Serverless: Invoke invoke
Serverless: [AWS lambda 200 1.555s 0 retries] invoke({ FunctionName: 'validate-stage-validate',
  InvocationType: 'RequestResponse',
  LogType: 'None',
  Payload: '***SensitiveInformation***' })
{
    "errorMessage": "Access Denied",
    "errorType": "AccessDenied",
    "stackTrace": [
        "Request.extractError (/var/task/node_modules/aws-sdk/lib/services/s3.js:585:35)",
        "Request.callListeners (/var/task/node_modules/aws-sdk/lib/sequential_executor.js:106:20)",
        "Request.emit (/var/task/node_modules/aws-sdk/lib/sequential_executor.js:78:10)",
        "Request.emit (/var/task/node_modules/aws-sdk/lib/request.js:683:14)",
        "Request.transition (/var/task/node_modules/aws-sdk/lib/request.js:22:10)",
        "AcceptorStateMachine.runTo (/var/task/node_modules/aws-sdk/lib/state_machine.js:14:12)",
        "/var/task/node_modules/aws-sdk/lib/state_machine.js:26:10",
        "Request.<anonymous> (/var/task/node_modules/aws-sdk/lib/request.js:38:9)",
        "Request.<anonymous> (/var/task/node_modules/aws-sdk/lib/request.js:685:12)",
        "Request.callListeners (/var/task/node_modules/aws-sdk/lib/sequential_executor.js:116:18)"
    ]
}

  Error --------------------------------------------------

  Error: Invoked function failed
      at AwsInvoke.log (/Users/myuser/.nvm/versions/node/v10.17.0/lib/node_modules/serverless/lib/plugins/aws/invoke/index.js:105:31)
  From previous event:
      at Object.invoke:invoke [as hook] (/Users/myuser/.nvm/versions/node/v10.17.0/lib/node_modules/serverless/lib/plugins/aws/invoke/index.js:23:12)
      at BbPromise.reduce (/Users/myuser/.nvm/versions/node/v10.17.0/lib/node_modules/serverless/lib/classes/PluginManager.js:489:55)
  From previous event:
      at PluginManager.invoke (/Users/myuser/.nvm/versions/node/v10.17.0/lib/node_modules/serverless/lib/classes/PluginManager.js:489:22)
      at getHooks.reduce.then (/Users/myuser/.nvm/versions/node/v10.17.0/lib/node_modules/serverless/lib/classes/PluginManager.js:524:24)
  From previous event:
      at PluginManager.run (/Users/myuser/.nvm/versions/node/v10.17.0/lib/node_modules/serverless/lib/classes/PluginManager.js:524:8)
      at variables.populateService.then (/Users/myuser/.nvm/versions/node/v10.17.0/lib/node_modules/serverless/lib/Serverless.js:115:33)
      at runCallback (timers.js:705:18)
      at tryOnImmediate (timers.js:676:5)
      at processImmediate (timers.js:658:5)
      at process.topLevelDomainCallback (domain.js:126:23)
  From previous event:
      at Serverless.run (/Users/myuser/.nvm/versions/node/v10.17.0/lib/node_modules/serverless/lib/Serverless.js:102:74)
      at serverless.init.then (/Users/myuser/.nvm/versions/node/v10.17.0/lib/node_modules/serverless/bin/serverless.js:72:30)
      at /Users/myuser/.nvm/versions/node/v10.17.0/lib/node_modules/serverless/node_modules/graceful-fs/graceful-fs.js:111:16
      at /Users/myuser/.nvm/versions/node/v10.17.0/lib/node_modules/serverless/node_modules/graceful-fs/graceful-fs.js:45:10
      at FSReqWrap.args [as oncomplete] (fs.js:140:20)
  From previous event:
      at initializeErrorReporter.then (/Users/myuser/.nvm/versions/node/v10.17.0/lib/node_modules/serverless/bin/serverless.js:72:8)
      at runCallback (timers.js:705:18)
      at tryOnImmediate (timers.js:676:5)
      at processImmediate (timers.js:658:5)
      at process.topLevelDomainCallback (domain.js:126:23)
  From previous event:
      at Object.<anonymous> (/Users/myuser/.nvm/versions/node/v10.17.0/lib/node_modules/serverless/bin/serverless.js:61:4)
      at Module._compile (internal/modules/cjs/loader.js:778:30)
      at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
      at Module.load (internal/modules/cjs/loader.js:653:32)
      at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
      at Function.Module._load (internal/modules/cjs/loader.js:585:3)
      at Function.Module.runMain (internal/modules/cjs/loader.js:831:12)
      at startup (internal/bootstrap/node.js:283:19)
      at bootstrapNodeJSCore (internal/bootstrap/node.js:623:3)

  Get Support --------------------------------------------
     Docs:          docs.serverless.com
     Bugs:          github.com/serverless/serverless/issues
     Issues:        forum.serverless.com

  Your Environment Information ---------------------------
     Operating System:          darwin
     Node Version:              10.17.0
     Framework Version:         1.56.1
     Plugin Version:            3.2.1
     SDK Version:               2.2.0
     Components Core Version:   1.1.2
     Components CLI Version:    1.4.0

The message I get back from https://api.serverless.com/core/tenants/[[my profileValue]] is {"errorMessage":"Not Found"} which is very suspect to me although I went back in my serverless user configuration and found no problems.

My serverless.yml configuration is as follows:

service: validate
app: api
org: l1nxit

custom:
  test: false
  inputBucket: l1nxit-schemas

provider:
  name: aws
  runtime: nodejs8.10

# defaults
  stage: stage
  region: eu-central-1
  user: serverless

# Lambda IAM Role
  iamRoleStatements:
    - Effect: "Allow"
      Action:
        - s3:GetObject
        - s3:GetObjectAcl
      Resource: "arn:aws:s3:::${self:custom.inputBucket}/*"

# packaging information
package:
  include:
    - node_modules/ajv/**
    - node_modules/fast-deep-equal/**
    - node_modules/fast-json-stable-stringify/**
    - node_modules/json-schema-traverse/**
    - node_modules/uri-js/**
  exclude:
    - S3/**
    - __tests__/**
    - .idea/**
    - coverage/**

functions:
  validate:
    handler: handler.validate
    environment:
      TEST: ${self:custom.test}
      INPUT_BUCKET: ${self:custom.inputBucket}

Any help would be much appreciated.

1

1 Answers

2
votes

To get objects from S3, it is important to have permission to list the bucket you want to get the objects from. In your iamRoleStatement, add the permission to do so:

- Effect: "Allow"
  Action:
    - "s3:ListBucket"
  Resource: "arn:aws:s3:::${self:custom.inputBucket}"