copilot-cli icon indicating copy to clipboard operation
copilot-cli copied to clipboard

Support APIGW as ingress for Backend Services

Open rmarapp-dio opened this issue 3 years ago • 32 comments

Hello,

Is there any guidance or support to implement API gateway to - 'Backend Service' integration. Does copilot have any support to integrate with API Gateway for backend services?

rmarapp-dio avatar Mar 12 '21 02:03 rmarapp-dio

Hi @rmarapp-prisidio ! We don't have an integration with APIGW available at the moment.

API Gateway for backend services?

Do you want the APIGW to be private? so that the APIGW is accessible only within the VPC or do you want it to be a public endpoint? At the moment the APIGW would need to be created outside of copilot unfortunately

efekarakus avatar Mar 15 '21 23:03 efekarakus

I think the use case is pretty simple (and common one IMHO)

  • Have apgw public endpoint that fronts the backend services.

Please let me know if you would like me to put in a feature request.

Thankyou efe

  • Ram

From: Efe Karakus @.> Date: Monday, March 15, 2021 at 6:22 PM To: aws/copilot-cli @.> Cc: Ram Marappan @.>, Mention @.> Subject: Re: [aws/copilot-cli] Integration with API Gateway and Backend Services (#2050)

Hi @rmarapp-prisidiohttps://github.com/rmarapp-prisidio ! We don't have an integration with APIGW available at the moment.

API Gateway for backend services?

Do you want the APIGW to be private? so that the APIGW is accessible only within the VPC or do you want it to be a public endpoint? At the moment the APIGW would need to be created outside of copilot unfortunately

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/aws/copilot-cli/issues/2050#issuecomment-799826272, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AS2346U3NBCFI6VF4FOTIBLTD2JEBANCNFSM4ZBN3I3A.

rmarapp-dio avatar Mar 15 '21 23:03 rmarapp-dio

Please let me know if you would like me to put in a feature request.

I updated this issue to be a feature request (renamed it!)

Would you mind sharing with us what features of APIGW you'd like to use with Copilot? 🙏 Any reason why you'd prefer to use APIGW over the existing "Load Balanced Web Service" pattern?

efekarakus avatar Mar 15 '21 23:03 efekarakus

Absolutely. We are build an product that has extra security requirements and by proxying it through API gateway we can govern access to the service and not expose the REST service to WWW and thus reducing the blast radius.

For most of the financial institutions this is a popular pattern. Pleas let me know if it makes sense.

Thanks Ram


From: Efe Karakus @.***> Sent: Monday, March 15, 2021 6:27 PM To: aws/copilot-cli Cc: Ram Marappan; Mention Subject: Re: [aws/copilot-cli] Support APIGW as ingress for Backend Services (#2050)

Please let me know if you would like me to put in a feature request.

I updated this issue to be a feature request (renamed it!)

Would you mind sharing with us what features of APIGW you'd like to use with Copilot? 🙏 Any reason why you'd prefer to use APIGW over the existing "Load Balanced Web Service" pattern?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/aws/copilot-cli/issues/2050#issuecomment-799828244, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AS2346VKVWI4OGFIHJNJEPLTD2JVXANCNFSM4ZBN3I3A.

rmarapp-dio avatar Mar 15 '21 23:03 rmarapp-dio

I think so, thanks! Is there a particular feature of APIGW that allows the RESTful service not to be accessible to the internet? Something like API Keys?

I'm trying to understand which particular features of APIGW we could expose in our manifest files to make it easier for you to integrate with it.

efekarakus avatar Mar 15 '21 23:03 efekarakus

Let me think about this.. give me a day or 2, please..

Thanks Ram


From: Efe Karakus @.> Sent: Monday, March 15, 2021 6:52:53 PM To: aws/copilot-cli @.> Cc: Ram Marappan @.>; Mention @.> Subject: Re: [aws/copilot-cli] Support APIGW as ingress for Backend Services (#2050)

I think so, thanks! Is there a particular feature of APIGW that allows the RESTful service not to be accessible to the internet? Something like API Keyshttps://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-setup-api-key-with-console.html?

I'm trying to understand which particular features of APIGW we could expose in our manifest files to make it easier for you to integrate with it.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/aws/copilot-cli/issues/2050#issuecomment-799838047, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AS2346XGYLHRYQQLTEI4IPDTD2MVLANCNFSM4ZBN3I3A.

rmarapp-dio avatar Mar 15 '21 23:03 rmarapp-dio

Efe,

Here are my thoughts

  • Start with Public REST API that integrates with a “back-end service”, that provides HTTP Proxy support along with CORS support @.***D71AB4.928C4260]

  • Expose properties for a list of stages and ability to pass an encryption key per stage.

  • Part of the recipe would be to tie usage plan with api-key and stage

Attaching 2 yaml files that does this. First is an svc that creates all the API GW stuff. Second is a web app that creates an API key and attaches to usage plan. Hope that helps.

Please let me know if you need anything more.

From: Ram @.> Date: Monday, March 15, 2021 at 6:54 PM To: aws/copilot-cli @.>, aws/copilot-cli @.> Cc: Mention @.> Subject: Re: [aws/copilot-cli] Support APIGW as ingress for Backend Services (#2050) Let me think about this.. give me a day or 2, please..


From: Efe Karakus @.> Sent: Monday, March 15, 2021 6:52:53 PM To: aws/copilot-cli @.> Cc: Ram @.>; Mention @.> Subject: Re: [aws/copilot-cli] Support APIGW as ingress for Backend Services (#2050)

I think so, thanks! Is there a particular feature of APIGW that allows the RESTful service not to be accessible to the internet? Something like API Keyshttps://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-setup-api-key-with-console.html?

I'm trying to understand which particular features of APIGW we could expose in our manifest files to make it easier for you to integrate with it.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/aws/copilot-cli/issues/2050#issuecomment-799838047, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AS2346XGYLHRYQQLTEI4IPDTD2MVLANCNFSM4ZBN3I3A.

rmarapp-dio avatar Mar 17 '21 03:03 rmarapp-dio

Thanks Ram! This is great :D

efekarakus avatar Mar 17 '21 17:03 efekarakus

Aboslutely, would be terrific for us if it get implemented! If there is something that we could do to help you guys out please let me know.

Thanks Ram

From: Efe Karakus @.> Date: Wednesday, March 17, 2021 at 12:53 PM To: aws/copilot-cli @.> Cc: Ram @.>, Mention @.> Subject: Re: [aws/copilot-cli] Support APIGW as ingress for Backend Services (#2050)

Thanks Ram! This is great :D

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/aws/copilot-cli/issues/2050#issuecomment-801288434, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AS2346TQEDS736WHOZK2NYLTEDUAVANCNFSM4ZBN3I3A.

rmarapp-dio avatar Mar 17 '21 20:03 rmarapp-dio

I think the key is https://aws.amazon.com/blogs/architecture/field-notes-integrating-http-apis-with-aws-cloud-map-and-amazon-ecs-services/ with routes secured by Cognito.

ceagan avatar Mar 26 '21 18:03 ceagan

Hello,

Any chance that this would get implemented near-term. We were going to start to implement it, but wanted check with the co-pilot team and see whether there are any plans for co-pilot support.

Any thoughts would be greatly appreciated.

From: Ram @.> Date: Wednesday, March 17, 2021 at 3:37 PM To: aws/copilot-cli @.>, aws/copilot-cli @.> Cc: Mention @.> Subject: Re: [aws/copilot-cli] Support APIGW as ingress for Backend Services (#2050) Aboslutely, would be terrific for us if it get implemented! If there is something that we could do to help you guys out please let me know.

Thanks Ram

From: Efe Karakus @.> Date: Wednesday, March 17, 2021 at 12:53 PM To: aws/copilot-cli @.> Cc: Ram Marappan @.>, Mention @.> Subject: Re: [aws/copilot-cli] Support APIGW as ingress for Backend Services (#2050)

Thanks Ram! This is great :D

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/aws/copilot-cli/issues/2050#issuecomment-801288434, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AS2346TQEDS736WHOZK2NYLTEDUAVANCNFSM4ZBN3I3A.

rmarapp-dio avatar Mar 27 '21 17:03 rmarapp-dio

I think the key is https://aws.amazon.com/blogs/architecture/field-notes-integrating-http-apis-with-aws-cloud-map-and-amazon-ecs-services/ with routes secured by Cognito.

Application Load Balancers also support integration with Cognito would that be something you'd be interested in to configure for existing "Load Balanced Web Services"?

How do y'all use Cognito today? I wonder if we can add a copilot auth init command to create an Amazon Cognito user pool via CloudFormation and attach it to your existing ALB 🤔

Any chance that this would get implemented near-term. We were going to start to implement it, but wanted check with the co-pilot team and see whether there are any plans for co-pilot support.

We really want to integrate with APIGW just like in the post from @ceagan but there is no short term plan for it. My first thought was that APIGW would instead be an option for "Load Balanced Web Services" if the APIGW is going to be publicly accessible:

type: "Load Balanced Web Service"
api:
   openapi: ./api-definition.json

How would you like this field to be surfaced in the manifest? What options would you like to see?

efekarakus avatar Mar 30 '21 18:03 efekarakus

Efe,

Apart from open-api I would like to pass in an

  • array of API-keys and stage-name,
  • Enable CORS support (Boolean)
  • domainName – Or this could be elmiated and use the domain name that was defined as part of the co-pilot app. This might be handy if we want vanity URL for the API-GW and external customers. This is more like “would like to have” Input

api:

openapi: ./api-definition.json

apiKeyStage:

  • Dsdskdjs, dev

enableCors: true|false

domainName:

Output:

  • Would be an API GW ID as an environment variable

Part of the recipe would be to tie api-key and stage with the api gateway instance something like this. @.***D7256B.7D2823F0]

From: Efe Karakus @.> Date: Tuesday, March 30, 2021 at 1:07 PM To: aws/copilot-cli @.> Cc: Ram @.>, Mention @.> Subject: Re: [aws/copilot-cli] Support APIGW as ingress for Backend Services (#2050)

I think the key is https://aws.amazon.com/blogs/architecture/field-notes-integrating-http-apis-with-aws-cloud-map-and-amazon-ecs-services/ with routes secured by Cognito.

Application Load Balancers also support integrationhttps://docs.aws.amazon.com/elasticloadbalancing/latest/application/listener-authenticate-users.html with Cognito would that be something you'd be interested in to configure for existing "Load Balanced Web Services"?

How do y'all use Cognito today? I wonder if we can add a copilot auth init command to create an Amazon Cognito user pool via CloudFormation and attach it to your existing ALB 🤔

Any chance that this would get implemented near-term. We were going to start to implement it, but wanted check with the co-pilot team and see whether there are any plans for co-pilot support.

We really want to integrate with APIGW just like in the post from @ceaganhttps://github.com/ceagan but there is no short term plan for it. My first thought was that APIGW would instead be an option for "Load Balanced Web Services" if the APIGW is going to be publicly accessible:

type: "Load Balanced Web Service"

api:

openapi: ./api-definition.json

How would you like this field to be surfaced in the manifest? What options would you like to see?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/aws/copilot-cli/issues/2050#issuecomment-810467959, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AS2346WZ5DY77T65RZSLLA3TGIHNZANCNFSM4ZBN3I3A.

rmarapp-dio avatar Mar 30 '21 18:03 rmarapp-dio

I’m sure it is true, but just confirming that the actually service will not be publicly accessible but only through API-GW.

From: Ram @.> Date: Tuesday, March 30, 2021 at 1:49 PM To: aws/copilot-cli @.>, aws/copilot-cli @.> Cc: Mention @.> Subject: Re: [aws/copilot-cli] Support APIGW as ingress for Backend Services (#2050) Efe,

Apart from open-api I would like to pass in an

  • array of API-keys and stage-name,
  • Enable CORS support (Boolean)
  • domainName – Or this could be elmiated and use the domain name that was defined as part of the co-pilot app. This might be handy if we want vanity URL for the API-GW and external customers. This is more like “would like to have” Input

api:

openapi: ./api-definition.json

apiKeyStage:

  • Dsdskdjs, dev

enableCors: true|false

domainName:

Output:

  • Would be an API GW ID as an environment variable

Part of the recipe would be to tie api-key and stage with the api gateway instance something like this. @.***D72581.E09B6C10]

From: Efe Karakus @.> Date: Tuesday, March 30, 2021 at 1:07 PM To: aws/copilot-cli @.> Cc: Ram @.>, Mention @.> Subject: Re: [aws/copilot-cli] Support APIGW as ingress for Backend Services (#2050)

I think the key is https://aws.amazon.com/blogs/architecture/field-notes-integrating-http-apis-with-aws-cloud-map-and-amazon-ecs-services/ with routes secured by Cognito.

Application Load Balancers also support integrationhttps://docs.aws.amazon.com/elasticloadbalancing/latest/application/listener-authenticate-users.html with Cognito would that be something you'd be interested in configuring for existing "Load Balanced Web Services"?

How do y'all use Cognito today? I wonder if we can add a copilot auth init command to create an Amazon Cognito user pool via CloudFormation and attach it to your existing ALB 🤔

Any chance that this would get implemented near-term. We were going to start to implement it, but wanted check with the co-pilot team and see whether there are any plans for co-pilot support.

We really want to integrate with APIGW just like in the post from @ceaganhttps://github.com/ceagan but there is no short-term plan for it. My first thought was that APIGW would instead be an option for "Load Balanced Web Services" if the APIGW is going to be publicly accessible:

type: "Load Balanced Web Service"

api:

openapi: ./api-definition.json

How would you like this field to be surfaced in the manifest? What options would you like to see?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/aws/copilot-cli/issues/2050#issuecomment-810467959, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AS2346WZ5DY77T65RZSLLA3TGIHNZANCNFSM4ZBN3I3A.

rmarapp-dio avatar Mar 30 '21 21:03 rmarapp-dio

Yup that's right! Copilot never creates security groups that allow ingress from the internet. For Load Balanced Web Services, only through the ALB or other containers in the cluster and it would be similar with the APIGW integration.

efekarakus avatar Mar 30 '21 22:03 efekarakus

So in case the ALB will not be visible publicly Correct?

From: Efe Karakus @.> Date: Tuesday, March 30, 2021 at 5:07 PM To: aws/copilot-cli @.> Cc: Ram @.>, Mention @.> Subject: Re: [aws/copilot-cli] Support APIGW as ingress for Backend Services (#2050)

Yup that's right! Copilot never creates security groups that allow ingress from the internet. For Load Balanced Web Services, only through the ALB or other containers in the cluster and it would be similar to the APIGW integration.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/aws/copilot-cli/issues/2050#issuecomment-810610185, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AS2346UPCESOI4NVLJEUBLDTGJDSHANCNFSM4ZBN3I3A.

rmarapp-dio avatar Mar 30 '21 22:03 rmarapp-dio

Right now the ALB is visible publicly for "Load Balanced Web Services", however if we do enable APIGW or ALB for "Backend Services" then they wouldn't be publicly visible.

efekarakus avatar Mar 31 '21 00:03 efekarakus

Perfect.

From: Efe Karakus @.> Date: Tuesday, March 30, 2021 at 7:46 PM To: aws/copilot-cli @.> Cc: Ram @.>, Mention @.> Subject: Re: [aws/copilot-cli] Support APIGW as ingress for Backend Services (#2050)

Right now the ALB is visible publicly for "Load Balanced Web Services", however, if we do enable APIGW or ALB for "Backend Services" then they wouldn't be publicly visible.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/aws/copilot-cli/issues/2050#issuecomment-810671167, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AS2346VUDPDQ67O2IAANDYLTGJWHVANCNFSM4ZBN3I3A.

rmarapp-dio avatar Mar 31 '21 02:03 rmarapp-dio

I think it is important to support authenticated routes with the deployed API Gateway too. They could be configured to use Amazon Cognito for authentication.

It would be great if there was an option to automatically deploy a Swagger-UI for the Copilot-deployed API as well. The Swagger-UI would be configured automatically to support in-browser testing of authenticated routes and allow developers/users of the API to access documentation of the deployed APIs.

ceagan avatar Mar 31 '21 14:03 ceagan

@efekarakus Any timeframe on when you think the team might be able to implement this feature, we have a need, and if it takes longer we might have to look at other options. Please let me know your thoughts.

rmarapp-dio avatar Apr 02 '21 14:04 rmarapp-dio

Hi @rmarapp-prisidio !

Any timeframe on when you think the team might be able to implement this feature

We don't have currently bandwidth to start on the implementation for this feature any time soon unfortunately. Our near-term roadmap is available here: https://github.com/aws/copilot-cli/projects/2

We were going to start to implement it

If y'all are still available to do it, we would love to have it as a contribution! But before implementation it would great to have a UX design discussion first such as https://github.com/aws/copilot-cli/issues/1154

However, in the mean time, I think it's possible to build this integration outside of Copilot with CloudFormation today although it won't be managed by Copilot.

In the service stack's we are exporting DiscoveryServiceARN and we also export the subnets and security groups created in the environment stack. So I think it should be possible to deploy a stack with APIGatewayV2:

PParameters:
  AppName:
    Type: String
  EnvName:
    Type: String
  SvcName:
    Type: String
Resources:
  CloudMapHttpApi:
    Type: AWS::ApiGatewayV2::Api
    Properties:
      ProtocolType: HTTP

  APIRoute:
    Type: AWS::ApiGatewayV2::Route
    Properties:
      ApiId: !Ref CloudMapHttpApi
      RouteKey: 'ANY /'
      Target: !Join
        - /
        - - integrations
          - !Ref APIIntegration

  PrivateAPIGWvpcLink:  
    Type: AWS::ApiGatewayV2::VpcLink
    Properties: 
      Name: private-apigw-vpclink
      SubnetIds:
      - Fn::Select:
        - 0
        - Fn::Split:
          - ','
          - Fn::ImportValue: !Sub '${AppName}-${EnvName}-PublicSubnets'
      - Fn::Select:
        - 1
        - Fn::Split:
          - ','
          - Fn::ImportValue: !Sub '${AppName}-${EnvName}-PublicSubnets'
      SecurityGroupIds:
      - Fn::ImportValue: !Sub '${AppName}-${EnvName}-EnvironmentSecurityGroup'

  APIIntegration:
    Type: AWS::ApiGatewayV2::Integration
    Properties:
      ApiId: !Ref CloudMapHttpApi
      IntegrationType: HTTP_PROXY
      IntegrationMethod: ANY
      ConnectionType: VPC_LINK
      ConnectionId: !Ref PrivateAPIGWvpcLink
      IntegrationUri: 
      - Fn::ImportValue: !Sub '${AppName}-${EnvName}-${SvcName}-DiscoveryServiceARN'
      PayloadFormatVersion: '1.0'  
  
  APIStage:
    Type: AWS::ApiGatewayV2::Stage
    Properties:
      StageName: $default
      AutoDeploy: true
      ApiId: !Ref CloudMapHttpApi

Outputs:
  APIURL:
    Description: Invoke URL
    Value: !Sub https://${CloudMapHttpApi}.execute-api.${AWS::Region}.amazonaws.com/        

Hope this helps!

efekarakus avatar Apr 02 '21 19:04 efekarakus

I have actually implemented this as an addon.

Parameters:
  App:
    Type: String
    Description: Your application's name.
  Env:
    Type: String
    Description: The environment name your service, job, or workflow is being deployed to.
  Name:
    Type: String
    Description: The name of the service, job, or workflow being deployed.

Resources:
  ApiGatewayV2Api:
    Type: "AWS::ApiGatewayV2::Api"
    Properties:
      Name: !Sub "${Name}.${Env}.${App}.example.com"
      ApiKeySelectionExpression: "$request.header.x-api-key"
      ProtocolType: "HTTP"
      RouteSelectionExpression: "$request.method $request.path"
      CorsConfiguration:
        AllowCredentials: false
        AllowHeaders:
          - "*"
        AllowMethods:
          - "*"
        AllowOrigins:
          - "*"
        ExposeHeaders:
          - "*"
        MaxAge: 0
      DisableExecuteApiEndpoint: false

  ApiGatewayV2Stage:
    Type: "AWS::ApiGatewayV2::Stage"
    Properties:
      StageName: "$default"
      ApiId: !Ref ApiGatewayV2Api
      AutoDeploy: true

  ApiGatewayV2Authorizer:
    Type: "AWS::ApiGatewayV2::Authorizer"
    Properties:
      ApiId: !Ref ApiGatewayV2Api
      AuthorizerType: "JWT"
      IdentitySource:
        - "$request.header.AuthorizationJWT"
      Name: "cognito"
      JwtConfiguration:
        Audience:
          - !Ref UserPoolClient
        Issuer: !Sub
          - "https://cognito-idp.${AWS::Region}.amazonaws.com/${PoolID}"
          - { PoolID: !Ref MyUserPool }

  MyCert:
    Type: AWS::CertificateManager::Certificate
    Properties:
      DomainName: !Sub "${Name}.${Env}.${App}.example.com"
      DomainValidationOptions:
        - DomainName: !Sub "${Name}.${Env}.${App}.example.com"
          HostedZoneId:
            Fn::ImportValue: !Sub "${App}-${Env}-HostedZone"
      ValidationMethod: DNS

  MyUserPool:
    Type: AWS::Cognito::UserPool
    Properties:
      UserPoolName: !Sub "${Name}.${Env}.${App}"

  UserPoolClient:
    Type: "AWS::Cognito::UserPoolClient"
    DependsOn: UserPoolResourceServer
    Properties:
      ClientName: !Sub "${Name}.${Env}.${App}"
      GenerateSecret: true
      UserPoolId: !Ref MyUserPool
      AllowedOAuthFlows:
        - client_credentials
      AllowedOAuthFlowsUserPoolClient: true
      SupportedIdentityProviders:
        - COGNITO
      AllowedOAuthScopes:
        - !Sub "${Name}.${Env}.${App}/api.readwrite"

  UserPoolDomain:
    Type: AWS::Cognito::UserPoolDomain
    Properties:
      Domain: !Sub "${Name}-${Env}-${App}"
      UserPoolId: !Ref MyUserPool

  UserPoolResourceServer:
    Type: AWS::Cognito::UserPoolResourceServer
    Properties:
      UserPoolId: !Ref MyUserPool
      Identifier: !Sub "${Name}.${Env}.${App}"
      Name: !Sub "${Name}.${Env}.${App}"
      Scopes:
        - ScopeName: "api.readwrite"
          ScopeDescription: "All access"

  MyApiMapping:
    Type: "AWS::ApiGatewayV2::ApiMapping"
    DependsOn: MyDomainName
    Properties:
      DomainName: !Sub "${Name}.${Env}.${App}.example.com"
      ApiId: !Ref ApiGatewayV2Api
      Stage: !Ref ApiGatewayV2Stage

  MyDomainName:
    Type: "AWS::ApiGatewayV2::DomainName"
    Properties:
      DomainName: !Sub "${Name}.${Env}.${App}.example.com"
      DomainNameConfigurations:
        - EndpointType: REGIONAL
          CertificateArn: !Ref MyCert
          CertificateName: !Sub "${Name}.${Env}.${App}.example.com"

  myDNSRecord:
    Type: AWS::Route53::RecordSet
    Properties:
      HostedZoneId:
        Fn::ImportValue: !Sub "${App}-${Env}-HostedZone"
      Name: !Sub "${Name}.${Env}.${App}.example.com"
      AliasTarget:
        HostedZoneId: !GetAtt MyDomainName.RegionalHostedZoneId
        DNSName: !GetAtt MyDomainName.RegionalDomainName
        EvaluateTargetHealth: true
      Type: A

  MyVpcLink:
    Type: AWS::ApiGatewayV2::VpcLink
    Properties:
      Name: !Sub "${App}-${Env}-${Name}"
      # Get exported ids from the parent stack that creates the VPC
      SubnetIds:
        !Split [",", Fn::ImportValue: !Sub "${App}-${Env}-PublicSubnets"]
      SecurityGroupIds:
        - Fn::ImportValue: !Sub "${App}-${Env}-EnvironmentSecurityGroup"

  ApiGatewayV2Integration:
    Type: "AWS::ApiGatewayV2::Integration"
    Properties:
      ApiId: !Ref ApiGatewayV2Api
      ConnectionId: !Ref MyVpcLink
      ConnectionType: "VPC_LINK"
      IntegrationMethod: "ANY"
      IntegrationType: "HTTP_PROXY"
      IntegrationUri: 
        Fn::ImportValue: !Sub "${App}-${Env}-${Name}-DiscoveryServiceARN"
      TimeoutInMillis: 30000
      PayloadFormatVersion: "1.0"

  ApiGatewayV2Route:
    Type: "AWS::ApiGatewayV2::Route"
    Properties:
      ApiId: !Ref ApiGatewayV2Api
      AuthorizerId: !Ref ApiGatewayV2Authorizer
      AuthorizationType: "JWT"
      # allow to all endpoints behind it
      RouteKey: "$default"
      Target: !Sub "integrations/${ApiGatewayV2Integration}"

sekamaneka avatar Apr 03 '21 09:04 sekamaneka

Wow this is amazing thanks for sharing it @swilso793 ! 🤩

efekarakus avatar Apr 03 '21 14:04 efekarakus

Awesome thanks for sharing. You saved us lot of work. We will give it a whirl!

Thanks Ram


From: swilso793 @.> Sent: Saturday, April 3, 2021 4:10:18 AM To: aws/copilot-cli @.> Cc: Ram Marappan @.>; Mention @.> Subject: Re: [aws/copilot-cli] Support APIGW as ingress for Backend Services (#2050)

I have actually implemented this as an addon.

Parameters: App: Type: String Description: Your application's name. Env: Type: String Description: The environment name your service, job, or workflow is being deployed to. Name: Type: String Description: The name of the service, job, or workflow being deployed.

Resources: ApiGatewayV2Api: Type: "AWS::ApiGatewayV2::Api" Properties: Name: !Sub "${Name}.${Env}.${App}.example.com" ApiKeySelectionExpression: "$request.header.x-api-key" ProtocolType: "HTTP" RouteSelectionExpression: "$request.method $request.path" CorsConfiguration: AllowCredentials: false AllowHeaders: - "" AllowMethods: - "" AllowOrigins: - "" ExposeHeaders: - "" MaxAge: 0 DisableExecuteApiEndpoint: false

ApiGatewayV2Stage: Type: "AWS::ApiGatewayV2::Stage" Properties: StageName: "$default" ApiId: !Ref ApiGatewayV2Api AutoDeploy: true

ApiGatewayV2Authorizer: Type: "AWS::ApiGatewayV2::Authorizer" Properties: ApiId: !Ref ApiGatewayV2Api AuthorizerType: "JWT" IdentitySource: - "$request.header.AuthorizationJWT" Name: "cognito" JwtConfiguration: Audience: - !Ref UserPoolClient Issuer: !Sub - "https://cognito-idp.${AWS::Region}.amazonaws.com/${PoolID}" - { PoolID: !Ref MyUserPool }

MyCert: Type: AWS::CertificateManager::Certificate Properties: DomainName: !Sub "${Name}.${Env}.${App}.example.com" DomainValidationOptions: - DomainName: !Sub "${Name}.${Env}.${App}.example.com" HostedZoneId: Fn::ImportValue: !Sub "${App}-${Env}-HostedZone" ValidationMethod: DNS

MyUserPool: Type: AWS::Cognito::UserPool Properties: UserPoolName: !Sub "${Name}.${Env}.${App}"

UserPoolClient: Type: "AWS::Cognito::UserPoolClient" DependsOn: UserPoolResourceServer Properties: ClientName: !Sub "${Name}.${Env}.${App}" GenerateSecret: true UserPoolId: !Ref MyUserPool AllowedOAuthFlows: - client_credentials AllowedOAuthFlowsUserPoolClient: true SupportedIdentityProviders: - COGNITO AllowedOAuthScopes: - !Sub "${Name}.${Env}.${App}/api.readwrite"

UserPoolDomain: Type: AWS::Cognito::UserPoolDomain Properties: Domain: !Sub "${Name}-${Env}-${App}" UserPoolId: !Ref MyUserPool

UserPoolResourceServer: Type: AWS::Cognito::UserPoolResourceServer Properties: UserPoolId: !Ref MyUserPool Identifier: !Sub "${Name}.${Env}.${App}" Name: !Sub "${Name}.${Env}.${App}" Scopes: - ScopeName: "api.readwrite" ScopeDescription: "All access"

MyApiMapping: Type: "AWS::ApiGatewayV2::ApiMapping" DependsOn: MyDomainName Properties: DomainName: !Sub "${Name}.${Env}.${App}.example.com" ApiId: !Ref ApiGatewayV2Api Stage: !Ref ApiGatewayV2Stage

MyDomainName: Type: "AWS::ApiGatewayV2::DomainName" Properties: DomainName: !Sub "${Name}.${Env}.${App}.example.com" DomainNameConfigurations: - EndpointType: REGIONAL CertificateArn: !Ref MyCert CertificateName: !Sub "${Name}.${Env}.${App}.example.com"

myDNSRecord: Type: AWS::Route53::RecordSet Properties: HostedZoneId: Fn::ImportValue: !Sub "${App}-${Env}-HostedZone" Name: !Sub "${Name}.${Env}.${App}.example.com" AliasTarget: HostedZoneId: !GetAtt MyDomainName.RegionalHostedZoneId DNSName: !GetAtt MyDomainName.RegionalDomainName EvaluateTargetHealth: true Type: A

MyVpcLink: Type: AWS::ApiGatewayV2::VpcLink Properties: Name: !Sub "${App}-${Env}-${Name}" # Get exported ids from the parent stack that creates the VPC SubnetIds: !Split [",", Fn::ImportValue: !Sub "${App}-${Env}-PublicSubnets"] SecurityGroupIds: - Fn::ImportValue: !Sub "${App}-${Env}-EnvironmentSecurityGroup"

ApiGatewayV2Integration: Type: "AWS::ApiGatewayV2::Integration" Properties: ApiId: !Ref ApiGatewayV2Api ConnectionId: !Ref MyVpcLink ConnectionType: "VPC_LINK" IntegrationMethod: "ANY" IntegrationType: "HTTP_PROXY" IntegrationUri: Fn::ImportValue: !Sub "${App}-${Env}-${Name}-DiscoveryServiceARN" TimeoutInMillis: 30000 PayloadFormatVersion: "1.0"

ApiGatewayV2Route: Type: "AWS::ApiGatewayV2::Route" Properties: ApiId: !Ref ApiGatewayV2Api AuthorizerId: !Ref ApiGatewayV2Authorizer AuthorizationType: "JWT" # allow to all endpoints behind it RouteKey: "$default" Target: !Sub "integrations/${ApiGatewayV2Integration}"

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/aws/copilot-cli/issues/2050#issuecomment-812838310, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AS2346TJVRJTZS7EBV6GAWLTG3LPVANCNFSM4ZBN3I3A.

rmarapp-dio avatar Apr 03 '21 15:04 rmarapp-dio

I did the following

  1. Changed my service from 'Loadbalanced web service' to 'Backend Service'
  2. Made minor modifications to the template file provided by @swilso793 and dropped it into the addons folder I keep getting the following error

No export named vault-rmar-dev-jasper-svc-DiscoveryServiceARN found. Rollback requested by user.

Any idea what I'm doing wrong? Any help would be greatly appreciated.

Thanks image

rmarapp-dio avatar Apr 04 '21 02:04 rmarapp-dio

I have patched copilot to make the namespaces differ based on environment.. You can check the issue out here.

https://github.com/aws/copilot-cli/issues/1929

Also:

copilot/api/addons/api-gateway.yaml:ApiGatewayV2Integration copilot/api/addons/api-gateway.yaml:ApiGatewayV2Route

Depend on the output of the parent stack. so they have to be commented out when first creating a service
Then run again with them enabled

sekamaneka avatar Apr 04 '21 08:04 sekamaneka

Thanks @swilso793. I've got most of it working. In terms of the use-case, I'm using a custom lambda authorizer and from the authorizer, I needed to call a co-pilot backend service. The lambda is not within the VPC so what is dns entry that I must use to invoke the back-end service. Or I need to set up an internal network loadbalancer and add fargate target groups to it etc.

@efekarakus, @swilso793 Is there an easy way to do this, or do I have to create an NLB. Thank you fo all the assitance. Super helpful.

I have patched copilot to make the namespaces differ based on environment.. You can check the issue out here.

#1929

Also:

copilot/api/addons/api-gateway.yaml:ApiGatewayV2Integration copilot/api/addons/api-gateway.yaml:ApiGatewayV2Route

Depend on the output of the parent stack. so they have to be commented out when first creating a service
Then run again with them enabled

rmarapp-dio avatar Apr 04 '21 19:04 rmarapp-dio

Sharing a tutorial here for how to setup http apis and ECS services: https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-private-integration.html

efekarakus avatar May 13 '21 00:05 efekarakus

We got this implemented few weeks ago to work alongside copilot and it works flawlessly well..

rmarapp-dio avatar May 13 '21 13:05 rmarapp-dio

Creating an API Gateway using the addon template works great. However, when I attempt to delete the copilot service that contains the addon, I get a Cloudformation error and the stack deletion cancels.

Export todo-dev-api-DiscoveryServiceARN cannot be deleted as it is in use by todo-dev-api-AddonsStack-1VK70SO7IGC4B

Shouldn't the copilot svc delete command also delete the addons nested stack?

Has anyone encountered this? The only workaround I have so far is to remove the addon folder, redeploy the copilot service - which removes the API Gateway, then delete the copilot service.

I'm curious if anyone else who added an API Gateway via an addon was able to delete the parent service.

Thanks!

dave-moser avatar Jul 19 '22 00:07 dave-moser