FormidableLabs / terraform-aws-serverless

Infrastructure support for Serverless framework apps, done the right way
https://registry.terraform.io/modules/FormidableLabs/serverless/aws
MIT License
144 stars 19 forks source link

CI policy seems to need ListStackResources #26

Closed declension closed 5 years ago

declension commented 5 years ago

Hi. Not sure if I'm doing something wrong here...

Assumptions

Steps

Expected

Success.

Actual

Getting an error about needing ListStackResources permissions (but these only exist on :

$ yarn sls deploy --stage ci --subfolder "$CI_ENVIRONMENT_NAME_SLUG"
yarn run v1.13.0
...
  Serverless Error ---------------------------------------

  User: arn:aws:iam::*********:user/my-user-name is not authorized to perform: cloudformation:ListStackResources on resource: arn:aws:cloudformation:us-east-1:********:stack/my-service-name-ci/*
ryan-roemer commented 5 years ago

That sounds like it should work. Would you be able to paste your terraform configuration into this ticket? And if possible the serverless config too? Anything you can paste, would be helpful! Thanks!

declension commented 5 years ago

Thanks, and sure. It's a bit abstracted / contained within some other stuff but the TF is roughly:

module "serverless" {
  source = "FormidableLabs/serverless/aws"

  region       = "${var.aws_region}"
  service_name = "${var.service_name}"
  stage        = "${var.environment}"
  sls_service_name = "${var.service_name}"
}

and the SLS is

service: my-service-name
frameworkVersion: ">1.26.0"

provider:
  name: aws
  region: us-east-1
  stage: ${opt:stage, 'ci'}

custom:
  subfolder: ${opt:subfolder, ''}
  bucketName: my-bucket-name-${opt:stage, 'ci'}
  s3Sync:
    - bucketName: ${self:custom.bucketName}
      bucketPrefix: ${self:custom.subfolder}
      localDir: dist/

plugins:
  - serverless-s3-sync

resources:
  Resources:
    AssetsBucket:
      Type: AWS::S3::Bucket
      Properties:
        BucketName: ${self:custom.bucketName}
        AccessControl: PublicRead
        WebsiteConfiguration:
          IndexDocument: index.html
          ErrorDocument: error.html

    StaticSiteS3BucketPolicy:
      Type: AWS::S3::BucketPolicy
      Properties:
        Bucket:
          Ref: AssetsBucket
        PolicyDocument:
          Statement:
            - Sid: PublicReadGetObject
              Effect: Allow
              Principal: "*"
              Action:
                - s3:GetObject
              Resource:
                Fn::Join: [
                  "", [
                  "arn:aws:s3:::",
                  {
                    "Ref": "AssetsBucket"
                  },
                  "/*"
                ]
                ]
ryan-roemer commented 5 years ago

Thanks. That should be enough to get me going. I’ll try and take a look at this later today or this week, but the first thing off the bat is that all policies and extra Iam permissions need to be placed in terraform, not serverless, Or a lot more permissions need to be placed in terraform to allow server less to do Iam grants like the one you have in config.

My plan is to work up a terraform solution for you, see if that works, and then possibly abstract that to a submodule specific to the plugin that you’re using. There’s probably going to be a lot of common plug-ins that we will need a sub module for under this locked down scheme.

My plan is to work up a terraform solution for you, see if that works, and then possibly abstract that to a submodule specific to the plug and you’re using. There’s probably going to be a lot of common plug-ins that we will need a sub module for under this lock down scheme.

Hope that loosely makes sense, and thanks for rolling with the punches as we cut our teeth on this module’s open source release!

declension commented 5 years ago

Ah, a change of error on using --verbose with sls (or maybe something else, hard to believe add verbose would change the error name):

  Serverless Error ---------------------------------------

  An error occurred: AssetsBucket - API: s3:PutBucketWebsite Access Denied.

Which sounds reasonable as locally, I'm the creator of the bucket, so syncing is easy, but in CI less so.

declension commented 5 years ago

..the first thing off the bat is that all policies and extra Iam permissions need to be placed in terraform, not serverless, Or a lot more permissions need to be placed in terraform to allow server less to do Iam grants like the one you have in config.

Oh, I feared this might be the case - doesn't that mean that "might as well do all infra config in Terraform" argument is reappearing? Last time I did this whole thing, it was a trial and error of giving away generic AWS permissions (on an IAM role / group) that were wide enough to allow existing and new Serverless projects to be set up by CI without TF involvement.

Anyway so I've given up on the Serverless side and put S3 bucket permissions back in some custom TF, which has fixed the S3 IAM errors, but the original ListStackResources is now back...

declension commented 5 years ago

Update: I've hacked this permission onto the group policy with some more Terraform, and it works, so I guess the original point stands - perhaps this is needed (for whatever reason) in non-admin roles?

ryan-roemer commented 5 years ago

Thanks. My developer role can sls deploy, but I haven't tried nuking all local state. Let me try that and see if there is some stateful artifact of doing an admin first sls deploy that avoids later calls to this.

And, in any case, I don't think there would be much harm in moving that IAM permission to developer/CI as it's already limited to service + stage.