Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(apigateway): resource policy configuration for private API #32719

Merged
merged 39 commits into from
Feb 10, 2025

Conversation

badmintoncryer
Copy link
Contributor

@badmintoncryer badmintoncryer commented Jan 3, 2025

Issue # (if applicable)

Closes #31660.

Reason for this change

The same PR is closed during maintainer's review. (#31692)

To create a Private API Gateway, we need to attach a resource policy that allows access only from specific Interface VPC Endpoints, as shown below.

new apigateway.RestApi(this, 'PrivateRestApi', {
      endpointTypes: [apigateway.EndpointType.PRIVATE],
      handler: fn,
      policy: new iam.PolicyDocument({
        statements: [
          new iam.PolicyStatement({
            principals: [new iam.AnyPrincipal],
            actions: ['execute-api:Invoke'],
            resources: ['execute-api:/*'],
            effect: iam.Effect.DENY,
            conditions: {
              StringNotEquals: {
                "aws:SourceVpce": vpcEndpoint.vpcEndpointId
              }
            }
          }),
          new iam.PolicyStatement({
            principals: [new iam.AnyPrincipal],
            actions: ['execute-api:Invoke'],
            resources: ['execute-api:/*'],
            effect: iam.Effect.ALLOW
          })
        ]
      })
    })

This is a bit troublesome.

Description of changes

  • Define IRestApi.addToResourcePolicy()
  • Implement addToResourcePolicy() at RestApi, SpecApi, and imported RestApi class
  • Implement RestApiBase.grantInvokeToVpcEndpoint()

In the grantInvokeToVpcEndpoint method, it was necessary to set a resource policy, and since a policy already existed in RestApiProps, I implemented it so that both can be used simultaneously.

Describe any new or updated permissions being added

Add 2 functions which modify resource policies.

Description of how you validated changes

Add both unit and integ tests.

Checklist


By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license

@aws-cdk-automation aws-cdk-automation requested a review from a team January 3, 2025 01:50
@github-actions github-actions bot added effort/medium Medium work item – several days of effort feature-request A feature should be added or improved. p2 distinguished-contributor [Pilot] contributed 50+ PRs to the CDK labels Jan 3, 2025
Copy link

codecov bot commented Jan 7, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 80.92%. Comparing base (775c009) to head (8caa834).
Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main   #32719   +/-   ##
=======================================
  Coverage   80.92%   80.92%           
=======================================
  Files         236      236           
  Lines       14253    14253           
  Branches     2490     2490           
=======================================
  Hits        11534    11534           
  Misses       2434     2434           
  Partials      285      285           
Flag Coverage Δ
suite.unit 80.92% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
packages/aws-cdk 79.73% <ø> (ø)
packages/aws-cdk-lib/core 82.20% <ø> (ø)

@aws-cdk-automation aws-cdk-automation added the pr/needs-community-review This PR needs a review from a Trusted Community Member or Core Team Member. label Jan 7, 2025
@badmintoncryer
Copy link
Contributor Author

@go-to-k Thank you very much!! This is exactly the kind of situation where lazy is useful… I’m sad that I didn’t think of it😭

I'll update my code including the function name.

@go-to-k
Copy link
Contributor

go-to-k commented Feb 7, 2025

@badmintoncryer

We might reflect the following in the integ test:

  • Call grantInvokeFromVpcEndpointsOnly twice
  • Call grantInvokeFromVpcEndpointsOnly with the same vpcEndpoint twice to check for duplicate deletion
    • This may possibly be overkill...
    this.api.grantInvokeFromVpcEndpointsOnly([vpcEndpoint1, vpcEndpoint2]);
    this.api.grantInvokeFromVpcEndpointsOnly([vpcEndpoint3]);
    this.api.grantInvokeFromVpcEndpointsOnly([vpcEndpoint3]);

I tried the above integ test in my environment and it seemed to work.

 "Policy": {
     "Statement": [
      {
       "Action": "execute-api:Invoke",
       "Condition": {
        "StringNotEquals": {
         "aws:SourceVpce": {
          "Fn::Join": [
           "",
           [
            {
             "Ref": "VpcVpcEndpoint1E6998B88"
            },
            ",",
            {
             "Ref": "VpcVpcEndpoint2469C3DB9"
            },
            ",",
            {
             "Ref": "VpcVpcEndpoint33172AEA2"
            }
           ]
          ]
         }
        }
       },
       "Effect": "Deny",
       "Principal": {
        "AWS": "*"
       },
       "Resource": "execute-api:/*"
      },
      {
       "Action": "execute-api:Invoke",
       "Effect": "Allow",
       "Principal": {
        "AWS": "*"
       },
       "Resource": "execute-api:/*"
      }
     ],
     "Version": "2012-10-17"
    }

@go-to-k
Copy link
Contributor

go-to-k commented Feb 7, 2025

We might reflect the following in the integ test:

This could be covered by unit tests only instead of an integ test...

Anyway, we'll need to cover these in unit tests.

@GavinZZ
Copy link
Contributor

GavinZZ commented Feb 7, 2025

Is it better to change the method name to grantInvokeFromVpcEndpoint"s"Only?

I'm not very confident about this approach. Do you have any better ideas?

How about using Lazy?

Nice, this is what I was considering too. Thanks for suggesting it!

@go-to-k
Copy link
Contributor

go-to-k commented Feb 8, 2025

@badmintoncryer

In the above example, string is passed to StringNotEquals, but thinking about it, should this have been an array. Please consider the above as just an example.

I tried the above integ test in my environment and it seemed to work.

Sorry, I haven't actually deployed it, I've only tried it up to synthesis. If something doesn't work, let me know.

@badmintoncryer
Copy link
Contributor Author

@go-to-k

Thank you! As you said, I wasn’t sure if the array handling would work, so I’m currently fixing the integ test and verifying it.

@go-to-k
Copy link
Contributor

go-to-k commented Feb 8, 2025

FYI

    const endpoints = Lazy.list({
      produce: () => {
        return Array.from(this._allowedVpcEndpoints).map(endpoint => endpoint.vpcEndpointId);
      },
    });
     "Statement": [
      {
       "Action": "execute-api:Invoke",
       "Condition": {
        "StringNotEquals": {
         "aws:SourceVpce": [
          {
           "Ref": "VpcVpcEndpoint1E6998B88"
          },
          {
           "Ref": "VpcVpcEndpoint2469C3DB9"
          },
          {
           "Ref": "VpcVpcEndpoint33172AEA2"
          }
         ]
        }
       },
       "Effect": "Deny",
       "Principal": {
        "AWS": "*"
       },
       "Resource": "execute-api:/*"
      },
      {
       "Action": "execute-api:Invoke",
       "Effect": "Allow",
       "Principal": {
        "AWS": "*"
       },
       "Resource": "execute-api:/*"
      }
     ],

@badmintoncryer
Copy link
Contributor Author

@go-to-k Thank you for your nice suggestion! I've used Lazy.list and updated integ test which validates execution of private api from multiple endpoints.

@go-to-k
Copy link
Contributor

go-to-k commented Feb 9, 2025

@badmintoncryer

Nice work! LGTM! But already approved :)

@badmintoncryer
Copy link
Contributor Author

@GavinZZ I've resolved all problems. Could you please confirm again?

@GavinZZ GavinZZ added pr/do-not-merge This PR should not be merged at this time. and removed pr/do-not-merge This PR should not be merged at this time. labels Feb 10, 2025
@GavinZZ
Copy link
Contributor

GavinZZ commented Feb 10, 2025

Thank you so much!! LGTM.

@aws-cdk-automation aws-cdk-automation removed the pr/needs-maintainer-review This PR needs a review from a Core Team Member label Feb 10, 2025
Copy link
Contributor

mergify bot commented Feb 10, 2025

Thank you for contributing! Your pull request will be updated from main and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork).

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildv2Project1C6BFA3F-wQm2hXv2jqQv
  • Commit ID: 8caa834
  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@mergify mergify bot merged commit 628e649 into aws:main Feb 10, 2025
19 of 20 checks passed
Copy link
Contributor

mergify bot commented Feb 10, 2025

Thank you for contributing! Your pull request will be updated from main and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork).

Copy link

Comments on closed issues and PRs are hard for our team to see.
If you need help, please open a new issue that references this one.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 10, 2025
@badmintoncryer badmintoncryer deleted the 31660-grantInvoke branch February 10, 2025 22:47
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
distinguished-contributor [Pilot] contributed 50+ PRs to the CDK effort/medium Medium work item – several days of effort feature-request A feature should be added or improved. p2
Projects
None yet
Development

Successfully merging this pull request may close these issues.

apigateway: Attaching a resource policy for a private API
4 participants