AWS:为什么我无法为嵌套堆栈分配自定义域? [英] AWS: Why I am unable to assign a custom domain to the nested stack?

查看:30
本文介绍了AWS:为什么我无法为嵌套堆栈分配自定义域?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将自定义域集成到 HTTP API 我正在使用 AWS API GatewayAWS Lambda 进行开发.我正在使用 AWS SAM 模板.在那里我有一个根堆栈和嵌套堆栈.

对于这个问题,我将使用一个带有一个嵌套堆栈的代码段.在那里,这就是我希望 URL 端点的方式

  1. 根堆栈 - api.example.com
  2. 嵌套堆栈 - api.example.com/nested

下面是我的代码

根堆栈

AWSTemplateFormatVersion: '2010-09-09'转换:AWS::Serverless-2016-10-31说明:>aws-restapiaws-restapi 的示例 SAM 模板# 更多关于 Globals 的信息:https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst全球:功能:超时:5虚拟主机配置:安全组 ID:- sg-041f24xxxx921e8e子网 ID:- 子网-0xxxxx2d参数:Firebase 项目 ID:类型:字符串#不要在 AWS 控制台中手动创建这个域,所以它会在这里失败域名:类型:字符串默认值:api.example.com资源:AuthGatewayHttpApi:类型:AWS::Serverless::HttpApi特性:领域:域名: !Ref 域名端点配置:区域CertificateArn: arn:aws:acm:us-east-1:xxxx:certificate/xxxx-420d-xxxx-b40d-xxxx路线53:HostedZoneId:xxxxxxxxxxx验证:授权人:Firebase授权器:身份来源:$request.header.AuthorizationJwt配置:观众:- !Ref FirebaseProjectId发行人:!Sub https://securetoken.google.com/${FirebaseProjectId}DefaultAuthorizer:FirebaseAuthorizer身份验证功能:类型:AWS::Serverless::Function特性:CodeUri:aws-restapi/处理程序:source/testfile.lambdaHandler运行时:nodejs14.x事件:网关:类型:HttpApi特性:ApiId: !Ref AuthGatewayHttpApi路径:/你好方法:获取嵌套堆栈二:依赖:AuthGatewayHttpApi类型:AWS::CloudFormation::Stack特性:模板网址:nested_stack.yaml参数:FirebaseProjectId: !Ref FirebaseProjectId域名: !Ref 域名

嵌套堆栈

AWSTemplateFormatVersion: '2010-09-09'转换:AWS::Serverless-2016-10-31说明:>aws-restapiaws-restapi 的示例 SAM 模板全球:功能:超时:5虚拟主机配置:安全组 ID:- sg-xxxxxxxxxxxx子网 ID:- 子网-xxxxxxxxxxxx参数:Firebase 项目 ID:类型:字符串域名:类型:字符串资源:AuthGatewayHttpApi2:类型:AWS::Serverless::HttpApi特性:领域:域名: !Ref 域名基本路径:两个端点配置:区域CertificateArn: arn:aws:acm:us-east-1:xxxxx:certificate/xxxxx-xxxx-xxxx-xxxx-xxxx路线53:HostedZoneId:xxxxxxxxxxxxxxx验证:授权人:Firebase授权器:身份来源:$request.header.AuthorizationJwt配置:观众:- !Ref FirebaseProjectId发行人:!Sub https://securetoken.google.com/${FirebaseProjectId}DefaultAuthorizer:FirebaseAuthorizer获取所有促销功能:类型:AWS::Serverless::Function # 有关函数资源的更多信息:https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction特性:CodeUri:aws-restapi/处理程序:source/promotions/promotions-getall.getAllPromotions运行时:nodejs14.x事件:获取所有促销API事件:类型:HttpApi # 更多关于 API 事件源的信息:https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api特性:路径:/promotions/getall方法:获取ApiId: !Ref AuthGatewayHttpApi2

但是我无法让它工作,因为嵌套堆栈无法创建.以下是错误

CREATE_FAILED AWS::CloudFormation::Stack NestedStackTwo嵌入式堆栈 arn:aws:cloudformation:us-east-1 xxxxx:stack/aws-restapi-NestedStackTwo-8KBISZRAVYBX/a3fcc010-0ce4-11ec-9c90-0e8a861a6983 未成功创建:以下资源创建失败:[ApiGatewayDomainNameV234ac706a57]

我相信这是因为根堆栈创建了域,而嵌套堆栈试图重新创建它而不是重用相同的域.

但是,这是一个有趣的事实;如果我使用 AWS API GATEWAY Web 控制台,我可以立即执行此操作.

我怎样才能让它在 aws-sam 中工作?

更新

根据用户 LRutten 的建议,我想出了以下嵌套堆栈的代码.

AWSTemplateFormatVersion: '2010-09-09'转换:AWS::Serverless-2016-10-31说明:>aws-restapiaws-restapi 的示例 SAM 模板全球:功能:超时:5虚拟主机配置:安全组 ID:- sg-xxxxxx子网 ID:- 子网-xxxxx参数:Firebase 项目 ID:类型:字符串域名:类型:字符串资源:AuthGatewayHttpApi2:类型:AWS::Serverless::HttpApi特性:验证:授权人:Firebase授权器:身份来源:$request.header.AuthorizationJwt配置:观众:- !Ref FirebaseProjectId发行人:!Sub https://securetoken.google.com/${FirebaseProjectId}DefaultAuthorizer:FirebaseAuthorizer我的API映射:类型:'AWS::ApiGatewayV2::ApiMapping'特性:域名: !Ref 域名ApiId: !Ref AuthGatewayHttpApi2阶段:生产我的域名:类型:'AWS::ApiGatewayV2::DomainName'特性:域名: !Ref 域名域名配置:- 端点类型:区域CertificateArn: arn:aws:acm:us-east-1:716460586643:certificate/bac44716-420d-431b-b40d-01378f20432d获取所有促销功能:类型:AWS::Serverless::Function # 有关函数资源的更多信息:https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction特性:CodeUri:aws-restapi/处理程序:source/promotions/promotions-getall.getAllPromotions运行时:nodejs14.x事件:GetAllPromotionsAPIEvent:类型:HttpApi # 更多关于 API 事件的信息来源:https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api特性:路径:/promotions/getall方法:获取ApiId: !Ref AuthGatewayHttpApi2

最终出现以下错误

嵌入式堆栈 arn:aws:cloudformation:us-east-1:716460586643:stack/aws-restapi-NestedStackTwo-14SAYLRO1WD1D/62336020-xx-xx-a04e-x 未成功创建:未能创建以下资源:[MyDomainName, MyApiMapping].

解决方案

确实,当您在那里指定域名称时,SAM 总是会创建域.它也在文档中说明.

要解决这个问题,您可以省略 AWS::Serverless::HttpApi 资源中的整个域配置,并自行编写 SAM 创建的资源.所以添加一个部分

类型:AWS::ApiGatewayV2::ApiMapping特性:ApiId:字符串ApiMappingKey:字符串域名:字符串阶段:字符串

文档

确保 ApiMapping 中的 Stage 属性也存在于 API 的 StageName 属性中.

还有一个

类型:AWS::ApiGatewayV2::DomainName特性:域名:字符串域名配置:- 域名配置相互Tls身份验证:相互认证标签: Json

文档

手动添加这些而不需要两次定义域本身应该可以解决问题.

woops 并没有真正思考.您当然应该只有映射,而不是域名本身:P.

I am trying to integrate a custom domain to the HTTP API I am developing with AWS API Gateway and AWS Lambda. I m using the AWS SAM template. There I have a root stack and nested stacks.

For this question I will use a code piece with a one nested stack. There, this is how I want the URL end points to be

  1. root stack - api.example.com
  2. nested stack - api.example.com/nested

Below is my code

Root stack

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  aws-restapi

  Sample SAM Template for aws-restapi
  
# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
  Function:
    Timeout: 5
    VpcConfig:
        SecurityGroupIds:
          - sg-041f24xxxx921e8e
        SubnetIds:
          - subnet-0xxxxx2d


Parameters:
  FirebaseProjectId:
    Type: String
  
  #Dont create this domain in the AWS Console manually, so it will fail here
  DomainName:
    Type: String
    Default: api.example.com

Resources:
  AuthGatewayHttpApi:
    Type: AWS::Serverless::HttpApi
    Properties:
      Domain:
        DomainName: !Ref DomainName
        EndpointConfiguration: REGIONAL
        CertificateArn: arn:aws:acm:us-east-1:xxxx:certificate/xxxx-420d-xxxx-b40d-xxxx
        Route53:
          HostedZoneId: xxxxxxxxxxx
      Auth:
        Authorizers:
          FirebaseAuthorizer:
            IdentitySource: $request.header.Authorization
            JwtConfiguration:
              audience:
                - !Ref FirebaseProjectId
              issuer: !Sub https://securetoken.google.com/${FirebaseProjectId}
        DefaultAuthorizer: FirebaseAuthorizer

 
  AuthFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: aws-restapi/
      Handler: source/testfile.lambdaHandler
      Runtime: nodejs14.x
      Events:
        Gateway:
          Type: HttpApi
          Properties:
            ApiId: !Ref AuthGatewayHttpApi
            Path: /hello
            Method: get

  NestedStackTwo:
    DependsOn: AuthGatewayHttpApi
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: nested_stack.yaml
      Parameters:
        FirebaseProjectId: !Ref FirebaseProjectId
        DomainName: !Ref DomainName

Nested stack

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  aws-restapi

  Sample SAM Template for aws-restapi

Globals:
  Function:
    Timeout: 5
    VpcConfig:
        SecurityGroupIds:
          - sg-xxxxxxxxxxxx
        SubnetIds:
          - subnet-xxxxxxxxxxx

Parameters:
  FirebaseProjectId:
    Type: String
  
  DomainName:
    Type: String

Resources:

  AuthGatewayHttpApi2:
    Type: AWS::Serverless::HttpApi
    Properties:
      Domain:
        DomainName: !Ref DomainName
        BasePath: two
        EndpointConfiguration: REGIONAL
        CertificateArn: arn:aws:acm:us-east-1:xxxxx:certificate/xxxxx-xxxx-xxxx-xxxx-xxxx
        Route53:
          HostedZoneId: xxxxxxxxxxxxx
      Auth:
        Authorizers:
          FirebaseAuthorizer:
            IdentitySource: $request.header.Authorization
            JwtConfiguration:
              audience:
                - !Ref FirebaseProjectId
              issuer: !Sub https://securetoken.google.com/${FirebaseProjectId}
        DefaultAuthorizer: FirebaseAuthorizer

  GetAllPromotionsFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      CodeUri: aws-restapi/
      Handler: source/promotions/promotions-getall.getAllPromotions
      Runtime: nodejs14.x
      Events:
        GetAllPromotionsAPIEvent:
          Type: HttpApi # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
          Properties:
            Path: /promotions/getall
            Method: get
            ApiId: !Ref AuthGatewayHttpApi2
  

However I cant get this to work because the nested stack fails to create. Below is the error

CREATE_FAILED                      AWS::CloudFormation::Stack         NestedStackTwo
                                                    

Embedded stack arn:aws:cloudformation:us-east-1 xxxxx:stack/aws-restapi-NestedStackTwo-8KBISZRAVYBX/a3fcc010-0ce4-11ec-9c90-0e8a861a6983 was not successfully created:

 The following resource(s) failed to create: [ApiGatewayDomainNameV234ac706a57] 

I believe this is happening because the root stack creates the domain and the nested stack is trying to re-create it instead of reusing the same.

But, here is the fun fact; if i use the AWS API GATEWAY web console, I can do this in no time.

How can I get this to work in aws-sam ?

UPDATE

Following the advice from the user LRutten, I came up with the following code for the nested stack.

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  aws-restapi

  Sample SAM Template for aws-restapi

Globals:
  Function:
    Timeout: 5
    VpcConfig:
        SecurityGroupIds:
          - sg-xxxxxx
        SubnetIds:
          - subnet-xxxxx

Parameters:
  FirebaseProjectId:
    Type: String
  
  DomainName:
    Type: String

Resources:

  AuthGatewayHttpApi2:
    Type: AWS::Serverless::HttpApi
    Properties:
      Auth:
        Authorizers:
          FirebaseAuthorizer:
            IdentitySource: $request.header.Authorization
            JwtConfiguration:
              audience:
                - !Ref FirebaseProjectId
              issuer: !Sub https://securetoken.google.com/${FirebaseProjectId}
        DefaultAuthorizer: FirebaseAuthorizer
  
  MyApiMapping:
    Type: 'AWS::ApiGatewayV2::ApiMapping'
    Properties:
      DomainName: !Ref DomainName
      ApiId: !Ref AuthGatewayHttpApi2
      Stage: prod
  
  MyDomainName:
    Type: 'AWS::ApiGatewayV2::DomainName'
    Properties:
      DomainName: !Ref DomainName
      DomainNameConfigurations:
        - EndpointType: REGIONAL
          CertificateArn: arn:aws:acm:us-east-1:716460586643:certificate/bac44716-420d-431b-b40d-01378f20432d


  GetAllPromotionsFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      CodeUri: aws-restapi/
      Handler: source/promotions/promotions-getall.getAllPromotions
      Runtime: nodejs14.x
      Events:
        GetAllPromotionsAPIEvent:
          Type: HttpApi # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
          Properties:
            Path: /promotions/getall
            Method: get
            ApiId: !Ref AuthGatewayHttpApi2

This ended up with the following error

Embedded stack arn:aws:cloudformation:us-east-1:716460586643:stack/aws-restapi-NestedStackTwo-14SAYLRO1WD1D/62336020-xx-xx-a04e-x was not successfully created:

The following resource(s) failed to create: [MyDomainName, MyApiMapping]. 

解决方案

Indeed SAM always creates the domain when you specify it's name there. It stated in the docs as well.

To get around this, you can omit the whole domain configuration in the AWS::Serverless::HttpApi resource and write the resources created by SAM yourself. So add a section with

Type: AWS::ApiGatewayV2::ApiMapping
Properties: 
  ApiId: String
  ApiMappingKey: String
  DomainName: String
  Stage: String

Docs

Make sure the Stage property in the ApiMapping is also present in the StageName property of the API.

And a

Type: AWS::ApiGatewayV2::DomainName
Properties: 
  DomainName: String
  DomainNameConfigurations: 
    - DomainNameConfiguration
  MutualTlsAuthentication: 
    MutualTlsAuthentication
  Tags: Json

Docs

Manually adding these without having the domain itself defined twice should do the trick.

Edit: woops wasn't really thinking straight. You should of course only have the mapping, not the domain name itself again :P.

这篇关于AWS:为什么我无法为嵌套堆栈分配自定义域?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆