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

AlwaysDeploy does not include GatewayResponse updates #3482

Closed
mousedownmike opened this issue Dec 24, 2023 · 7 comments
Closed

AlwaysDeploy does not include GatewayResponse updates #3482

mousedownmike opened this issue Dec 24, 2023 · 7 comments
Labels
area/api-gateway blocked/close-if-inactive Blocked for >14 days with no response, will be closed if still inactive after 7 days blocked/more-info-needed More info is needed from the requester. If no response in 14 days, it will become stale.

Comments

@mousedownmike
Copy link

Description

Setting AlwaysDeploy: true on an AWS::Serverless::Api resource does not pick up changes to AWS::ApiGateway::GatewayResponse resources when the API is deployed.

AlwaysDeploy was introduced in #2935

Steps to reproduce

  1. Create a SAM Template with an AWS::Serverless::Api and a AWS::ApiGateway::GatewayResponse that references the API in the RestApiId property.
  2. Set the AlwaysDeploy property on the API to be true.
  3. Perform the initial deployment of the SAM Template.
  4. Modify the AWS::ApiGateway::GatewayResponse in some fashion.
  5. Re-deploy the SAM Template

Observed result

  • The GatewayResponse changes appear in the console.
  • The API has been redeployed as seen in the API Gateway Deployment History Tab
  • Requests that should be receiving the updated GatewayResponse are unchanged.

Expected result

I expected the API Deployment to pick up the changes to the GatewayResponse properties.

Work Around

Manually deploying the API in the AWS API Gateway Console causes the GatewayResponse changes to be picked up.

Additional environment details

Here is a snippet of my SAM template where I am experiencing this:

Resources:
  ContactAppGateway:
    Type: AWS::Serverless::Api
    Properties:
      OpenApiVersion: 3.0.1
      StageName: stage
      AlwaysDeploy: true
      Auth:
        Authorizers:
          ContactAppAuthorizer:
            UserPoolArn: !GetAtt ContactAppUserPool.Arn
            Identity:
              Header: Authorization
      Domain:
        BasePath: ""
        DomainName: !Ref gatewayDomain
        CertificateArn: !Ref GatewayCert
        SecurityPolicy: TLS_1_2
        EndpointConfiguration: REGIONAL
        Route53:
          HostedZoneId: !Ref domainZone
  UnauthorizedRedirect:
    Type: AWS::ApiGateway::GatewayResponse
    Properties:
      ResponseTemplates:
        text/html: |
          <html>
              <head>
                  <meta 
                    http-equiv="refresh" 
                    content="0;url=/shell?target=$context.path">
              </head>
              <body></body>
          </html>
      ResponseType: UNAUTHORIZED
      RestApiId: !Ref ContactAppGateway
      StatusCode: '401'
@mousedownmike mousedownmike added the stage/needs-triage Automatically applied to new issues and PRs, indicating they haven't been looked at. label Dec 24, 2023
@GavinZZ
Copy link
Contributor

GavinZZ commented Dec 27, 2023

Hi there, thanks for opening an issue. It would often result in weird behaviour if you mix SAM resources with regular CloudFormation resources. I would recommend defining the gateway response as part of the openapi specification in DefintionBody or DefinitionUri property of your SAM API. An simple example is given here:

openapi: 3.0.0
info:
  title: Sample API
  version: 1.0.0
paths:
  /someEndpoint:
    get:
      summary: Sample endpoint
      responses:
        '401':
          description: Unauthorized access. The client will be redirected.
          content:
            text/html:
              schema:
                type: string
                example: |
                  <html>
                    <head>
                      <meta 
                        http-equiv="refresh" 
                        content="0;url=/shell?target=$context.path">
                    </head>
                    <body></body>
                  </html>

@mousedownmike
Copy link
Author

Thanks @GavinZZ, unfortunately, I don't think this will work for my use case. The responses I'm manipulating are generated by the CognitoAuthorizer, not by any of my mapped endpoints. As far as I understand things, your solution would require the request getting past the authorizer before those response transformations were implemented.

@GavinZZ
Copy link
Contributor

GavinZZ commented Dec 30, 2023

@mousedownmike I spent some time and wrote an example following your description. However, I cannot reproduce this problem.

I'm using a simple template like the following

Transform: AWS::Serverless-2016-10-31
Resources:
  MyApi:
    Type: AWS::Serverless::Api
    Properties:
      StageName: MyNewStageName
      DefinitionBody:
        # Simple HTTP Proxy API
        openapi: '3.0'
        info:
          version: '2016-09-23T22:23:23Z'
          title: Simple Api
        basePath: /demo
        schemes:
        - https
        paths:
          /http/{proxy+}:
            x-amazon-apigateway-any-method:
              parameters:
              - name: proxy
                in: path
              x-amazon-apigateway-integration:
                type: http_proxy
                uri: http://httpbin.org/{proxy}
                httpMethod: ANY
                passthroughBehavior: when_no_match
                requestParameters:
                  integration.request.path.proxy: method.request.path.proxy
  UnauthorizedRedirect:
    Type: AWS::ApiGateway::GatewayResponse
    Properties:
      ResponseTemplates:
        text/html: |
          <html>
              <head>
                  <meta 
                    http-equiv="refresh" 
                    content="0;url=/shell?target=$context.path">
              </head>
              <body></body>
          </html>
      ResponseType: UNAUTHORIZED
      RestApiId: !Ref MyApi
      StatusCode: '401'

Note that this template includes a SAM API, a AWS::ApiGateway::GatewayResponse resource. I am able to deploy this template successfully for the first time.

Then I proceeded with updating the AWS::ApiGateway::GatewayResponse resource

  UnauthorizedRedirect:
      ResponseType: UNAUTHORIZED
      RestApiId: !Ref MyApi
      StatusCode: '403'

I then tried to deploy this updated template again and I am able to deploy it and I can see changes reflected in the console as well. So I'm not able to reproduce the issue described.

To be super clear, this problem is not related to AlwaysDeploy as this property only works with properties changed in SAM API resource itself. Also, since the GatewayResponse resource depends on the API resource (implicit depends on through the RestApiId: !Ref MyApi), changes in AWS::ApiGateway::GatewayResponse should always be deployed prior to deploying the API resource. If a change is not recognized, this is most likely not a SAM issue but a CloudFormation or ApiGateway issue.

@GavinZZ GavinZZ added blocked/more-info-needed More info is needed from the requester. If no response in 14 days, it will become stale. area/api-gateway blocked/close-if-inactive Blocked for >14 days with no response, will be closed if still inactive after 7 days and removed stage/needs-triage Automatically applied to new issues and PRs, indicating they haven't been looked at. labels Dec 30, 2023
@mousedownmike
Copy link
Author

@GavinZZ, thank you for your time on this. Without using an Authorizer on the API, I don't think it replicates the experience I was having. To be clear, I do see the changes reflected in the console when I apply the template. The problem is that they don't actually function for responses generated by the Authorizer. From my understanding of what you're saying, it sounds like that's expected.

I might recommend a minor documentation update for the AlwaysDeploy property to call out the fact that changes to standard CloudFormation resources "should always be deployed prior to deploying the API resource". Unfortunately, using a DependsOn relationship doesn't appear to guarantee that (or, quite possibly, I didn't test that properly).

Ultimately, I've decided not to use the GatewayResponse resources because they just don't offer the flexibility I was hoping for... specifically, no $context interpolation in headers. I've opted to use Lambda@Edge functions to manipulate the respones as necessary.

Copy link
Contributor

github-actions bot commented Jan 1, 2024

⚠️COMMENT VISIBILITY WARNING⚠️

Comments on closed issues are hard for our team to see.
If you need more assistance, please either tag a team member or open a new issue that references this one.
If you wish to keep having a conversation with other community members under this issue feel free to do so.

@mousedownmike mousedownmike closed this as not planned Won't fix, can't repro, duplicate, stale Jan 1, 2024
Copy link
Contributor

github-actions bot commented Jan 1, 2024

⚠️COMMENT VISIBILITY WARNING⚠️

Comments on closed issues are hard for our team to see.
If you need more assistance, please either tag a team member or open a new issue that references this one.
If you wish to keep having a conversation with other community members under this issue feel free to do so.

@GavinZZ
Copy link
Contributor

GavinZZ commented Jan 2, 2024

@mousedownmike thanks for the suggestion, I'm going to create a task internally for doc update to clearly state the limitation of AlwaysDeploy property.

To be clear, I do see the changes reflected in the console when I apply the template. The problem is that they don't actually function for responses generated by the Authorizer. From my understanding of what you're saying, it sounds like that's expected.

That's definitely not expected, but all SAM Transform does it to transform the template into standard CloudFormation template. Specifically in your scenario, this problem seems to be an issue on ApiGateway side or CloudFormation side. Unfortunately, there's not much SAM can do since the transformed template looks valid.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/api-gateway blocked/close-if-inactive Blocked for >14 days with no response, will be closed if still inactive after 7 days blocked/more-info-needed More info is needed from the requester. If no response in 14 days, it will become stale.
Projects
None yet
Development

No branches or pull requests

2 participants