sst / sst

SST v2
https://v2.sst.dev
MIT License
21.35k stars 1.63k forks source link

Permission Boundary Issues #3597

Open cgcompassion opened 8 months ago

cgcompassion commented 8 months ago

One of the interesting problems we hit is that our AWS setup requires all IAM roles to have a specific permissions boundary applied (DevBoundary). There is no good way yet to enforce that in SST.

The Error

Three different failures to do with creating roles in the bootstrap process. Here's one of them (with sensitive data redacted):

CDKToolkit |  2/12 | 7:18:46 AM | CREATE_FAILED        | AWS::IAM::Role          | ImagePublishingRole Resource handler returned message: "User: arn:aws:sts::97_________2:assumed-role/AWSReservedSSO_____________/C____@____.org is not authorized to perform: iam:CreateRole on resource: arn:aws:iam::_________:role/cdk-hnb659fds-image-publishing-role-________-us-east-2 with an explicit deny in an identity-based policy (Service: Iam, Status Code: 403, Request ID: 5_________0)" (RequestToken: 9___________1, HandlerErrorCode: AccessDenied)

Things I Tried that did not work

Applying to config (this works, but not for all the roles in the bootstrap template):

export default {
  config(_input) {
    return {
      name: "deploy",
      region: "us-east-2",
      cdk: {
        customPermissionsBoundary: 'DevBoundary'
      }
    };
  },

Applying to the stack:

  const boundary = iam.ManagedPolicy.fromAwsManagedPolicyName('DevBoundary');
  iam.PermissionsBoundary.of(stack).apply(boundary);

Applying to the app:

  stacks(app) {
    const boundary = iam.ManagedPolicy.fromAwsManagedPolicyName('DevBoundary');
    iam.PermissionsBoundary.of(app).apply(boundary);

    app.stack(Backend, { permissionsBoundary: PermissionsBoundary.fromName('DevBoundary') });
  }

Adding a cdk.context.json with the following:

{
    "@aws-cdk/core:permissionsBoundary": {
        "name": "DevBoundary"
    }
}

How I finally got it working

I had to export the bootstrap template using

cdk bootstrap --show-template > template.yaml

Then, modify the template, adding this block to every AWS::IAM::Role:

      PermissionsBoundary:
        Fn::If:
          - PermissionsBoundarySet
          - Fn::Sub: arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/${InputPermissionsBoundary}
          - Ref: AWS::NoValue

There are 5 roles in the template, and only one of them already has this block applied.

And finally, I updated the InputPermissionsBoundary to default to our custom DevBoundary.

Then I had to install the cdk cli and use that to bootstrap CDK with the altered template. Now that it's done, it shouldn't need to be done again unless we move to a different AWS account, or someone destroys the CDKToolkit stack in CloudFormation.

cgcompassion commented 8 months ago

Related Issues: https://github.com/sst/sst/issues/3105 https://github.com/sst/sst/issues/1056

jayair commented 8 months ago

It might be that we missed these after our recent updates. Can you share all the ones that failed? So we can go update them internally?

cgcompassion commented 8 months ago

Sure. The one that already had the code block is: CloudFormationExecutionRole and the ones that I added the code block to are:

jayair commented 8 months ago

Thanks! I'll check.

fwang commented 7 months ago

@cgcompassion hmm.. looking at CDK's bootstrap template, the permission boundary is indeed only set on the ExecutionRolehttps://github.com/aws/aws-cdk/blob/6a7a24afcc1ebebf71c267b890732a455e865cc8/packages/aws-cdk/lib/api/bootstrap/bootstrap-template.yaml#L554-L558

SST could patch CDK's template.. but keeping the patch up to date over time might be tricky.

Best option here might be to submit a PR to CDK. I can nudge them to expedite the review.