copilot-cli
copilot-cli copied to clipboard
Expose target group ARN as stack output
Context
I have a short term need for my load balanced web service to support an external domain name. My understanding is that this will be added as a feature to Copilot, but it will not be available for at least two months. See #1188.
In the meantime, I would like to create a workaround, which involves adding listener rules and certificates for the external domain to the load balancer created by Copilot. The CloudFormation template for an addon would look like this:
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.
Mappings:
CustomDomains:
...
Resources:
HTTPListenerRule:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
Actions:
- Type: redirect
RedirectConfig:
Protocol: HTTPS
Port: 443
Host: "#{host}"
Path: "/#{path}"
Query: "#{query}"
StatusCode: HTTP_301
Conditions:
- Field: 'host-header'
HostHeaderConfig:
Values: !FindInMap [CustomDomains, !Ref Env, CustomDomains]
- Field: 'path-pattern'
PathPatternConfig:
Values:
- "/*"
ListenerArn:
Fn::ImportValue: !Sub '${App}-${Env}-HTTPListenerArn'
Priority: 40000
HTTPSListenerRule:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
Actions:
- TargetGroupArn: !Ref TargetGroup
Type: forward
Conditions:
- Field: 'host-header'
HostHeaderConfig:
Values: !FindInMap [CustomDomains, !Ref Env, CustomDomains]
- Field: 'path-pattern'
PathPatternConfig:
Values:
- "/*"
Fn::ImportValue: !Sub '${App}-${Env}-HTTPSListenerArn'
Priority: 40000
HTTPSCertificate:
Type: AWS::ElasticLoadBalancingV2::ListenerCertificate
Properties:
Certificates: !FindInMap [CustomDomains, !Ref Env, Certificates]
ListenerArn:
Fn::ImportValue: !Sub '${App}-${Env}-HTTPSListenerArn'
There is one missing piece to getting this working, however. The TargetGroup
resource and ARN are not available to addons.
Feature Proposal
I propose adding it as an output to the service's stack. I think it would be a matter of adding the following to the templates/workloads/services/lb-web/cf.yml
file:
TargetGroupARN:
Description: ARN of the Target Group.
Value: !GetAtt TargetGroup.Arn
Export:
Name: !Sub "${AppName}-${EnvName}-${WorkloadName}-TargetGroupARN"
@sugarjig Thanks for this suggestion!
My use case: I'd like the ability to add a listener rule to block a certain path. The ability to add a listener rule with a rule condition to restrict access to a sensitive route. I suppose a workaround would be to do it with a WAF rule.
e.g. a source IP rule for one of the following:
- /open-api
- /admin
- /dashboard
Hello @matthewhembree. Seems like you can utilize customizing addons parameters to do the same thing since the target group is created in the service stack.
Hi @iamhopaul123 . I'm not following what you mean. I want to add a listener rule, but I need the ListenerArn:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
Actions:
- Action
Conditions:
- RuleCondition
ListenerArn: String # Need this.
Priority: Integer
Hello @matthewhembree. Listener arn should be included as one of the outputs of the environment stack. Can you import it as
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
Actions:
- Action
Conditions:
- RuleCondition
ListenerArn:
Fn::ImportValue: !Sub '${App}-${Env}-HTTPSListenerArn'
Priority: Integer
@efekarakus
+1 for the initial request for exposing TargetGroupARN
as a stack output.
I'm deploying my own CloudFront distribution in front of copilot to work around the issue described here: https://github.com/aws/copilot-cli/issues/4394#issuecomment-1402106907. This means that I have a custom domain name, not managed through copilot, that I need to route through the copilot ALB to the correct target group. I got everything working with a custom HTTPSListenerRule
, but the downside is that I have to hardcode the target group ARN in my service addon template. My template looks basically the same as @sugarjig's.
@mlazar-endear hi! We're actively working on #4208 and #4209 that should unlock that use case of specifying additional outputs
The new CFN patching feature solved this beautifully for me. Instead of using an addon to define a custom HTTPSListenerRule
, I can simply patch the existing rule to point to my cloudfront domain!
- op: replace
path: /Resources/HTTPSListenerRule/Properties/Conditions/0/HostHeaderConfig/Values
value:
- my-custom.domain
Closing this as you can now use yaml patch to export anything from the CloudFormation stack ❤️