aws / copilot-cli

The AWS Copilot CLI is a tool for developers to build, release and operate production ready containerized applications on AWS App Runner or Amazon ECS on AWS Fargate.
https://aws.github.io/copilot-cli/
Apache License 2.0
3.52k stars 417 forks source link

[Bug]: Template format error: Unresolved resource dependencies [NLBCertValidatorAction] in the Resources block of the template #5923

Open bryceandress opened 2 months ago

bryceandress commented 2 months ago

Description:

After importing ACM certificate and while trying to migrate NLB listener from 80/tcp to 443/tls I received the error

Template format error: Unresolved resource dependencies [NLBCertValidatorAction] in the Resources block of the template

from Cloudformation

Details:

copilot version: v1.34.0

Observed result:

Failure to deploy

Expected result:

Successful TLS Listener

Debugging:

I was able to make this work with the following cfn patches but obviously not ideal

- op: add
  path: /Resources/NLBListener/Properties
  value:
    Certificates:
      - CertificateArn: <redacted>
    Port: 443
    Protocol: TLS
    SslPolicy: ELBSecurityPolicy-TLS13-1-2-2021-06
    DefaultActions:
      - TargetGroupArn: !Ref NetworkLoadBalancerTargetGroup
        Type: forward
    LoadBalancerArn: !Ref PublicNetworkLoadBalancerV2

- op: remove
  path: /Resources/NLBCertValidatorAction

- op: remove
  path: /Resources/NLBCertValidatorFunction

- op: remove
  path: /Resources/NLBCertValidatorRole
iamhopaul123 commented 2 months ago

After importing ACM certificate and while trying to migrate NLB listener from 80/tcp to 443/tls I received the error

Hello @bryceandress would you mind to paste your manifest here? I need more information for what steps you took for the migration.

bryceandress commented 2 months ago

copilot/environments/production/manifest.yml

# The manifest for the "production" environment.
# Read the full specification for the "Environment" type at:
#  https://aws.github.io/copilot-cli/docs/manifest/environment/

# Your environment name will be used in naming your resources like VPC, cluster, etc.
name: production
type: Environment

# Import your own VPC and subnets or configure how they should be created.
network:
  vpc:
    cidr: 10.1.0.0/16
    subnets:
      public:
        - cidr: 10.1.0.0/24
          az: us-east-1a
        - cidr: 10.1.1.0/24
          az: us-east-1b
      private:
        - cidr: 10.1.2.0/24
          az: us-east-1a
        - cidr: 10.1.3.0/24
          az: us-east-1b

# Configure the load balancers in your environment, once created.
http:
  deregistration_delay: 60
  public:
    certificates:
      - <redacted>

# Configure observability for your environment resources.
observability:
  container_insights: true

copilot/api/manifest.yml

 name: api
type: Load Balanced Web Service

# Configuration for your containers and service.
image:
  # Docker build arguments. For additional overrides: https://aws.github.io/copilot-cli/docs/manifest/lb-web-service/#image-build
  build: Dockerfile
  # Port exposed through your container to route traffic to it.
  port: 8000

environments:
  production:
    # Distribute traffic to your service.
    http: false
    nlb:
      port: 443/tls
      target_port: 8000
      healthcheck:
        port: 8000
        healthy_threshold: 2
        unhealthy_threshold: 2
        interval: 5s
        timeout: 2s

    deployment:
      cpu: 256
      memory: 512
    platform: linux/arm64  # See https://aws.github.io/copilot-cli/docs/manifest/lb-web-service/#platform
    exec: true     # Enable running commands in your container.
    network:
      connect: true # Enable Service Connect for intra-environment traffic between services.

    count:
      range: 1-20
      cooldown:
        in: 60s
        out: 10s
      cpu_percentage: 50

    variables:
      WEB_CONCURRENCY: 1

overrides.yml

 - op: replace
  path: /Resources/LogGroup/Properties/RetentionInDays
  value: 1
- op: add
  path: /Resources/PublicNetworkLoadBalancerV2/Properties/LoadBalancerAttributes
  value:
    - "Key": "deletion_protection.enabled"
      "Value": "true"
    - "Key": "load_balancing.cross_zone.enabled"
      "Value": "true"
- op: add
  path: /Resources/GlobalAccelerator
  value:
    Type: AWS::GlobalAccelerator::Accelerator
    Properties:
      Name: !Sub "${AppName}-${EnvName}-Accelerator"
      IpAddressType: IPV4
      Enabled: true

- op: add
  path: /Resources/GlobalAcceleratorListener
  value:
    Type: AWS::GlobalAccelerator::Listener
    Properties:
      AcceleratorArn: !Ref GlobalAccelerator
      Protocol: TCP
      PortRanges:
        - FromPort: 443
          ToPort: 443
      ClientAffinity: NONE
- op: add
  path: /Resources/GlobalAcceleratorEndpointGroup
  value:
    Type: AWS::GlobalAccelerator::EndpointGroup
    Properties:
      ListenerArn: !Ref GlobalAcceleratorListener
      EndpointGroupRegion: !Ref "AWS::Region"
      EndpointConfigurations:
        - EndpointId: !Ref PublicNetworkLoadBalancerV2
      TrafficDialPercentage: 100
      HealthCheckProtocol: TCP
      HealthCheckIntervalSeconds: 30
      HealthCheckPath: /
      HealthCheckPort: 443
- op: replace
  path: /Outputs/PublicNetworkLoadBalancerDNSName
  value:
    Description: "DNS Name of the Global Accelerator"
    Value: !GetAtt GlobalAccelerator.DnsName
- op: add
  path: /Resources/NLBListener/Properties
  value:
    Certificates:
      - CertificateArn: <certificate arn>
    Port: 443
    Protocol: TLS
    SslPolicy: ELBSecurityPolicy-TLS13-1-2-2021-06
    DefaultActions:
      - TargetGroupArn: !Ref NetworkLoadBalancerTargetGroup
        Type: forward
    LoadBalancerArn: !Ref PublicNetworkLoadBalancerV2

- op: remove
  path: /Resources/NLBCertValidatorAction

- op: remove
  path: /Resources/NLBCertValidatorFunction

- op: remove
  path: /Resources/NLBCertValidatorRole
iamhopaul123 commented 2 months ago

Could it because you added

- op: remove
 path: /Resources/NLBCertValidatorAction

which caused the nil reference for

    Certificates:
      - CertificateArn: !Ref NLBCertValidatorAction

this CFN snippet that we autogenerated? Or did you do that on purpose because you wanted to use a custom cert?

bryceandress commented 2 months ago

I had to add that in to use the custom certificate, unless I'm mistaken and there was an easier step I could have taken.

iamhopaul123 commented 2 months ago

Yeah it doesn't seem to be supported to use custom certs unless using override...So your workaround is the only way for now. Would you mind me ask why you need a custom cert?

bryceandress commented 2 months ago

We have a workload that benefits from the low latency of NLBs in comparison to ALBs however we still required SSL. We have no need for E2E, so termination of the SSL at the NLBs was acceptable.

Happy to hear any other recommendations though if there is something simpler we are missing.

bryceandress commented 2 months ago

Guess that didn't really answer your question. We wanted to tie the NLB to our domain which unless I'm mistaken that is only possible with a custom cert.

iamhopaul123 commented 2 months ago

We wanted to tie the NLB to our domain which unless I'm mistaken that is only possible with a custom cert.

Not really. NLBCertValidatorAction is supposed to help you add any A-record to the hosted zone with the alias you specified in the manifest. However, if you didn't create your app with copilot app init --domain xyz, which means the hosted zone is not managed by Copilot, I think you current workaround is probably the only way.

bryceandress commented 2 months ago

Thanks, yea unfortunately I had already initiated the app. We also have DNS handled in a parent AWS account. Thanks for looking into this!