Как мне настроить мой пользовательский домен PUBLI C AWS для разрешения лямбды, настроенной для моего VP C? - PullRequest
0 голосов
/ 22 марта 2020

Что работает:

Использование безсерверной инфраструктуры :

  • Я настроил AWS VP C
  • У меня настроена база данных Amazon Aurora для моего VP C
  • У меня есть лямбда-шлюз API AWS, настроенный для моего VP C
  • Когда Я развернул свою лямбду, я могу получить к ней доступ публично через сгенерированный AWS URL: XXX.execute-api.us-east-1.amazon aws .com / prod / outages
  • В моей лямбде я выполняю очень простой запрос, который доказывает, что я могу подключиться к своей базе данных.

Все это отлично работает.

Что НЕ работает:

  • Я зарегистрировал домен с AWS / Route 53 и добавил сертификат (например, * .foo.com)

  • Я использую плагин serverless-domain-manager , чтобы сделать мою лямбду доступной через мой домен (например, api.foo.com / outages разрешается в XXX .Execute-api.us-восток-1.amazon aws .com / Prod / отключения ) * 1 043 *

Это нормально работает, если моя лямбда НЕ настроена для моего VP C

Но когда моя лямбда IS настроена для моего VP C пользовательский домен api.foo.com / outages НЕ разрешается в XXX.execute-api.us-east-1.amazon aws .com / prod / outages

Иными словами: я могу НЕ получить доступ api.foo.com / отключения публично.

Что мне нужно:

1 - XXX.execute-api.us-east-1.amazon aws .com / prod / отключение доступно публично (это работает)

2 - Мой пользовательский домен, api.foo.com / перебоям указывает на ЖЕ лямбду как XXX.execute-api.us -east-1.amazon aws .com / prod / outages (в моем VP C) и доступен публично (не работает. Я получаю: {"message": "Запрещено"})

virtual-private-cloud.yml

service: virtual-private-cloud

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

custom:
  appVersion: 0.0.0
  VPC_CIDR: 10

resources:
  Resources:
    ServerlessVPC:
      Type: AWS::EC2::VPC
      Properties:
        CidrBlock: ${self:custom.VPC_CIDR}.0.0.0/16
        EnableDnsSupport: true
        EnableDnsHostnames: true
        InstanceTenancy: default
    ServerlessSubnetA:
      DependsOn: ServerlessVPC
      Type: AWS::EC2::Subnet
      Properties:
        VpcId:
          Ref: ServerlessVPC
        AvailabilityZone: ${self:provider.region}a
        CidrBlock: ${self:custom.VPC_CIDR}.0.0.0/24
    ServerlessSubnetB:
      DependsOn: ServerlessVPC
      Type: AWS::EC2::Subnet
      Properties:
        VpcId:
          Ref: ServerlessVPC
        AvailabilityZone: ${self:provider.region}b
        CidrBlock: ${self:custom.VPC_CIDR}.0.1.0/24
    ServerlessSubnetC:
      DependsOn: ServerlessVPC
      Type: AWS::EC2::Subnet
      Properties:
        VpcId:
          Ref: ServerlessVPC
        AvailabilityZone: ${self:provider.region}c
        CidrBlock: ${self:custom.VPC_CIDR}.0.2.0/24

  Outputs:
    VPCDefaultSecurityGroup:
      Value:
        Fn::GetAtt:
          - ServerlessVPC
          - DefaultSecurityGroup
      Export:
        Name: VPCDefaultSecurityGroup-${self:provider.stage}
    SubnetA:
      Description: 'Subnet A.'
      Value: !Ref ServerlessSubnetA
      Export:
        Name: vpc-subnet-A-${self:provider.stage}
    SubnetB:
      Description: 'Subnet B.'
      Value: !Ref ServerlessSubnetB
      Export:
        Name: vpc-subnet-B-${self:provider.stage}
    SubnetC:
      Description: 'Subnet C.'
      Value: !Ref ServerlessSubnetC
      Export:
        Name: vpc-subnet-C-${self:provider.stage} 

database-service.yml

service: database-service

provider:
  name: aws
  region: us-east-1
  stage: ${opt:stage, dev}
  environment:
    stage: ${opt:stage, dev}

plugins:
  - serverless-plugin-ifelse

custom:
  appVersion: 0.0.1
  AURORA:
    DB_NAME: database${self:provider.stage}
    USERNAME: ${ssm:/my-db-username~true}
    PASSWORD: ${ssm:/my-db-password~true}
    HOST:
      Fn::GetAtt: [AuroraRDSCluster, Endpoint.Address]
    PORT:
      Fn::GetAtt: [AuroraRDSCluster, Endpoint.Port]
  serverlessIfElse:
    - If: '"${opt:stage}" == "prod"'
      Set:
        resources.Resources.AuroraRDSCluster.Properties.EngineMode: provisioned
      ElseSet:
        resources.Resources.AuroraRDSCluster.Properties.EngineMode: serverless
        resources.Resources.AuroraRDSCluster.Properties.ScalingConfiguration.MinCapacity: 1
        resources.Resources.AuroraRDSCluster.Properties.ScalingConfiguration.MaxCapacity: 4

      ElseExclude:
        - resources.Resources.AuroraRDSInstanceParameter
        - resources.Resources.AuroraRDSInstance

resources:
  Resources:
    AuroraSubnetGroup:
      Type: AWS::RDS::DBSubnetGroup
      Properties:
        DBSubnetGroupDescription: "Aurora Subnet Group"
        SubnetIds:
          - 'Fn::ImportValue': vpc-subnet-A-${self:provider.stage}
          - 'Fn::ImportValue': vpc-subnet-B-${self:provider.stage}
          - 'Fn::ImportValue': vpc-subnet-C-${self:provider.stage}
    AuroraRDSClusterParameter:
      Type: AWS::RDS::DBClusterParameterGroup
      Properties:
        Description: Parameter group for the Serverless Aurora RDS DB.
        Family: aurora5.6
        Parameters:
          character_set_database: "utf32"
    AuroraRDSCluster:
      Type: "AWS::RDS::DBCluster"
      Properties:
        MasterUsername: ${self:custom.AURORA.USERNAME}
        MasterUserPassword: ${self:custom.AURORA.PASSWORD}
        DBSubnetGroupName:
          Ref: AuroraSubnetGroup
        Engine: aurora
        EngineVersion: "5.6.10a"
        DatabaseName: ${self:custom.AURORA.DB_NAME}
        BackupRetentionPeriod: 3
        DBClusterParameterGroupName:
          Ref: AuroraRDSClusterParameter
        VpcSecurityGroupIds:
          - 'Fn::ImportValue': VPCDefaultSecurityGroup-${self:provider.stage}

    # this is needed for non-serverless mode
    AuroraRDSInstanceParameter:
      Type: AWS::RDS::DBParameterGroup
      Properties:
        Description: Parameter group for the Serverless Aurora RDS DB.
        Family: aurora5.6
        Parameters:
          sql_mode: IGNORE_SPACE
          max_connections: 100
          wait_timeout: 900
          interactive_timeout: 900

    # this is needed for non-serverless mode
    AuroraRDSInstance:
      Type: "AWS::RDS::DBInstance"
      Properties:
        DBInstanceClass: db.t2.small
        DBSubnetGroupName:
          Ref: AuroraSubnetGroup
        Engine: aurora
        EngineVersion: "5.6.10a"
        PubliclyAccessible: false
        DBParameterGroupName:
          Ref: AuroraRDSInstanceParameter
        DBClusterIdentifier:
          Ref: AuroraRDSCluster

  Outputs:
    DatabaseName:
      Description: 'Database name.'
      Value: ${self:custom.AURORA.DB_NAME}
      Export:
        Name: DatabaseName-${self:provider.stage}
    DatabaseHost:
      Description: 'Database host.'
      Value: ${self:custom.AURORA.HOST}
      Export:
        Name: DatabaseHost-${self:provider.stage}
    DatabasePort:
      Description: 'Database port.'
      Value: ${self:custom.AURORA.PORT}
      Export:
        Name: DatabasePort-${self:provider.stage}

outage-service.yml

service: outage-service

package:
  individually: true

plugins:
  - serverless-bundle
  - serverless-plugin-ifelse
  - serverless-domain-manager

custom:
  appVersion: 0.0.12
  stage: ${opt:stage}
  domains:
    prod: api.foo.com
    test: test-api.foo.com
    dev: dev-api.foo.com
  customDomain:
    domainName: ${self:custom.domains.${opt:stage}}
    stage: ${opt:stage}
    basePath: outages
    custom.customDomain.certificateName: "*.foo.com"
    custom.customDomain.certificateArn: 'arn:aws:acm:us-east-1:395671985612:certificate/XXXX'
    createRoute53Record: true
  serverlessIfElse:
    - If: '"${opt:stage}" == "prod"'
      Set:
          custom.customDomain.enabled: true
      ElseSet:
          custom.customDomain.enabled: false

provider:
  name: aws
  runtime: nodejs12.x
  stage: ${opt:stage}
  region: us-east-1
  environment:
    databaseName: !ImportValue DatabaseName-${self:provider.stage}
    databaseUsername: ${ssm:/my-db-username~true}
    databasePassword: ${ssm:/my-db-password~true}
    databaseHost: !ImportValue DatabaseHost-${self:provider.stage}
    databasePort: !ImportValue DatabasePort-${self:provider.stage}

functions:
  hello:
    memorySize: 2048
    timeout: 30
    handler: functions/handler.hello
    vpc:
      securityGroupIds:
        - 'Fn::ImportValue': VPCDefaultSecurityGroup-${self:provider.stage}
      subnetIds:
        - 'Fn::ImportValue': vpc-subnet-A-${self:provider.stage}
        - 'Fn::ImportValue': vpc-subnet-B-${self:provider.stage}
        - 'Fn::ImportValue': vpc-subnet-C-${self:provider.stage}
    environment:
      functionName: getTowns
    events:
      - http:
          path: outage
          method: get
          cors:
            origin: '*'
            headers:
              - Content-Type
              - authorization

resources:
  - Outputs:
      ApiGatewayRestApiId:
        Value:
          Ref: ApiGatewayRestApi
        Export:
          Name: ${self:custom.stage}-ApiGatewayRestApiId

      ApiGatewayRestApiRootResourceId:
        Value:
           Fn::GetAtt:
            - ApiGatewayRestApi
            - RootResourceId 
        Export:
          Name: ${self:custom.stage}-ApiGatewayRestApiRootResourceId

1 Ответ

0 голосов
/ 23 марта 2020

Полагаю, вы могли пропустить добавление конечных точек VP C для API Gateway.

Убедитесь, что вы создали конечную точку интерфейса VP C для API GW и используете ее в создаваемом API. Это позволит API-запросам к лямбде, работающим в VP C

Ссылки:

  1. https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-private-apis.html#apigateway -private-api-create-interface-vp c - конечная точка
  2. https://aws.amazon.com/blogs/compute/introducing-amazon-api-gateway-private-endpoints/

Надеюсь, это поможет !!

...