pulumi / pulumi-awsx

AWS infrastructure best practices in component form!
https://www.pulumi.com/docs/guides/crosswalk/aws/
Apache License 2.0
227 stars 104 forks source link

ValidationError: A certificate must be specified for HTTPS listeners #1242

Closed dan-cooke closed 6 months ago

dan-cooke commented 8 months ago

What happened?

I have been stuck on this one for a while. When trying to set up a https listener on my ApplicationLoadBalancer I am receiving a validation error saying that I have not attached a certificate

Example

import * as aws from '@pulumi/aws';
import { loadBalancerDomain } from './service';
// eslint-disable-next-line @nx/enforce-module-boundaries
import { getDomain } from '../../../libs/infra/src/util';

const zoneId = aws.route53
  .getZone({
    name: getDomain(),
  })
  .then((zone) => {
    return zone.zoneId;
  });

new aws.route53.Record(getDomain('api'), {
  name: getDomain('api'),
  zoneId: zoneId,
  ttl: 30,
  type: 'CNAME',
  records: [loadBalancerDomain],
  allowOverwrite: true,
});

const cert = new aws.acm.Certificate('api-cert', {
  domainName: getDomain('api'),
  validationMethod: 'DNS',
});

const certRecord = new aws.route53.Record('api-cert-validation-record', {
  name: cert.domainValidationOptions[0].resourceRecordName,
  records: [cert.domainValidationOptions[0].resourceRecordValue],
  ttl: 60,
  type: cert.domainValidationOptions[0].resourceRecordType,
  zoneId,
});

const certValidation = new aws.acm.CertificateValidation(
  'api-cert-validation',
  {
    certificateArn: cert.arn,
    validationRecordFqdns: [certRecord.fqdn],
  }
);

const apiLoadBalancer = new awsx.lb.ApplicationLoadBalancer('templi-lb', {
  subnetIds: baseInfra.requireOutput('vpcPublicSubnetIds'),
  securityGroups: [apiSecurityGroup.id],
  defaultTargetGroup: {
    protocol: 'HTTP',
    port: 80,
    targetType: 'ip',
    vpcId: baseInfra.requireOutput('vpcId'),

    healthCheck: {
      path: '/health',
      port: '80',
      protocol: 'HTTP',
    },
  },

  listener: {
    port: 443,
    protocol: 'HTTPS',
    sslPolicy: 'ELBSecurityPolicy-TLS13-1-2-2021-06',
    certificateArn: cert.arn,
  },
});

Output of pulumi about


CLI
Version      3.107.0
Go Version   go1.22.0
Go Compiler  gc

Plugins
NAME    VERSION
nodejs  unknown

Host
OS       arch
Version
Arch     x86_64

This project is written in nodejs: executable='/run/user/1000/fnm_multishells/3378_1710588590343/bin/node' version='v20.9.0'

Current Stack: templi/templi-api/prod

TYPE                                                 URN
pulumi:pulumi:Stack                                  urn:pulumi:prod::templi-api::pulumi:pulumi:Stack::templi-api-prod
pulumi:providers:aws                                 urn:pulumi:prod::templi-api::pulumi:providers:aws::default_6_25_1
pulumi:providers:pulumi                              urn:pulumi:prod::templi-api::pulumi:providers:pulumi::default
aws:acm/certificate:Certificate                      urn:pulumi:prod::templi-api::aws:acm/certificate:Certificate::api-cert
aws:rds/parameterGroup:ParameterGroup                urn:pulumi:prod::templi-api::aws:rds/parameterGroup:ParameterGroup::templi-database-parameter-group
aws:route53/record:Record                            urn:pulumi:prod::templi-api::aws:route53/record:Record::api-cert-validation-record
aws:acm/certificateValidation:CertificateValidation  urn:pulumi:prod::templi-api::aws:acm/certificateValidation:CertificateValidation::api-cert-validation
pulumi:pulumi:StackReference                         urn:pulumi:prod::templi-api::pulumi:pulumi:StackReference::templi/templi-infra/prod
aws:rds/subnetGroup:SubnetGroup                      urn:pulumi:prod::templi-api::aws:rds/subnetGroup:SubnetGroup::templi-database-subnet-group
pulumi:providers:awsx                                urn:pulumi:prod::templi-api::pulumi:providers:awsx::default_2_5_0
aws:ec2/securityGroup:SecurityGroup                  urn:pulumi:prod::templi-api::aws:ec2/securityGroup:SecurityGroup::templi-api-sg
awsx:ecr:Image                                       urn:pulumi:prod::templi-api::awsx:ecr:Image::templi-api
pulumi:providers:aws                                 urn:pulumi:prod::templi-api::pulumi:providers:aws::default_6_9_0
aws:ec2/securityGroup:SecurityGroup                  urn:pulumi:prod::templi-api::aws:ec2/securityGroup:SecurityGroup::templi-database-sg
aws:rds/instance:Instance                            urn:pulumi:prod::templi-api::aws:rds/instance:Instance::templi-database
pulumi:providers:docker                              urn:pulumi:prod::templi-api::pulumi:providers:docker::default_4_5_0
docker:index/image:Image                             urn:pulumi:prod::templi-api::awsx:ecr:Image$docker:index/image:Image::6f49d865-container
awsx:lb:ApplicationLoadBalancer                      urn:pulumi:prod::templi-api::awsx:lb:ApplicationLoadBalancer::templi-lb
aws:lb/targetGroup:TargetGroup                       urn:pulumi:prod::templi-api::awsx:lb:ApplicationLoadBalancer$aws:lb/targetGroup:TargetGroup::templi-lb
aws:lb/loadBalancer:LoadBalancer                     urn:pulumi:prod::templi-api::awsx:lb:ApplicationLoadBalancer$aws:lb/loadBalancer:LoadBalancer::templi-lb
aws:lb/listener:Listener                             urn:pulumi:prod::templi-api::awsx:lb:ApplicationLoadBalancer$aws:lb/listener:Listener::templi-lb-0
awsx:ecs:FargateService                              urn:pulumi:prod::templi-api::awsx:ecs:FargateService::templi-api
aws:route53/record:Record                            urn:pulumi:prod::templi-api::aws:route53/record:Record::api.templi.ai
awsx:ecs:FargateTaskDefinition                       urn:pulumi:prod::templi-api::awsx:ecs:FargateService$awsx:ecs:FargateTaskDefinition::templi-api
aws:iam/role:Role                                    urn:pulumi:prod::templi-api::awsx:ecs:FargateService$awsx:ecs:FargateTaskDefinition$aws:iam/role:Role::templi-api-execution
aws:cloudwatch/logGroup:LogGroup                     urn:pulumi:prod::templi-api::awsx:ecs:FargateService$awsx:ecs:FargateTaskDefinition$aws:cloudwatch/logGroup:LogGroup::templi-api
aws:iam/role:Role                                    urn:pulumi:prod::templi-api::awsx:ecs:FargateService$awsx:ecs:FargateTaskDefinition$aws:iam/role:Role::templi-api-task
aws:iam/rolePolicyAttachment:RolePolicyAttachment    urn:pulumi:prod::templi-api::awsx:ecs:FargateService$awsx:ecs:FargateTaskDefinition$aws:iam/rolePolicyAttachment:RolePolicyAttachment::templi-api-execution-9a42f520
aws:ecs/taskDefinition:TaskDefinition                urn:pulumi:prod::templi-api::awsx:ecs:FargateService$awsx:ecs:FargateTaskDefinition$aws:ecs/taskDefinition:TaskDefinition::templi-api
aws:ecs/service:Service                              urn:pulumi:prod::templi-api::awsx:ecs:FargateService$aws:ecs/service:Service::templi-api

Found no pending operations associated with prod

Backend
Name           pulumi.com
URL            https://app.pulumi.com/dan-cooke
User           dan-cooke
Organizations  dan-cooke, templi
Token type     personal

Additional context

No response

Contributing

Vote on this issue by adding a 👍 reaction. To contribute a fix for this issue, leave a comment (and link to your pull request, if you've opened one already).

mjeffryes commented 8 months ago

Thanks for reporting this @dan-cooke, do you happen to have the exact text of the error message you received?

dan-cooke commented 8 months ago

@mjeffryes wow I swore I put the error text in 😅 let me see if I can reproduce it

but from memory the error text is basically the issue title

flostadler commented 6 months ago

Hey @dan-cooke, yes the title has the correct error message.

Is the certificate in the ISSUED state? If not can you try adding an explicit dependency on the certificate validation to the ALB please? Like so:

const apiLoadBalancer = new awsx.lb.ApplicationLoadBalancer('templi-lb', {/*...*/}, { dependsOn: [certValidation] });

I'm also gonna try and reproduce this on our end in the meantime

flostadler commented 6 months ago

I'm not able to reproduce the issue locally (pulumi 3.113.1, awsx 2.9.0, aws 6.34.0). This here deploys successfully:

import * as aws from "@pulumi/aws";
import * as awsx from "@pulumi/awsx";

const vpc = new awsx.ec2.Vpc("florian-test-vpc");

const parentDomain = "REPLACE_WITH_PARENT_DOMAIN";

const parentZone = aws.route53
  .getZone({
    name: parentDomain,
  })
  .then((zone) => {
    return zone.zoneId;
  });

const subdomain = `florian.${parentDomain}`;
const subZone = new aws.route53.Zone(subdomain, {
    name: subdomain,
})

new aws.route53.Record(`${subdomain}.NS`, {
    name: subdomain,
    zoneId: parentZone,
    ttl: 30,
    type: 'NS',
    records: subZone.nameServers,
    allowOverwrite: true,
  });

const cert = new aws.acm.Certificate('api-cert', {
  domainName: subdomain,
  validationMethod: 'DNS',
});

const certRecord = new aws.route53.Record('api-cert-validation-record', {
  name: cert.domainValidationOptions[0].resourceRecordName,
  records: [cert.domainValidationOptions[0].resourceRecordValue],
  ttl: 60,
  type: cert.domainValidationOptions[0].resourceRecordType,
  zoneId: subZone.zoneId,
});

const certValidation = new aws.acm.CertificateValidation(
  'api-cert-validation',
  {
    certificateArn: cert.arn,
    validationRecordFqdns: [certRecord.fqdn],
  }
);

const apiLoadBalancer = new awsx.lb.ApplicationLoadBalancer('api-lb', {
  subnetIds: vpc.publicSubnetIds,
  defaultTargetGroup: {
    protocol: 'HTTP',
    port: 80,
    targetType: 'ip',
    vpcId: vpc.vpcId,

    healthCheck: {
      path: '/health',
      port: '80',
      protocol: 'HTTP',
    },
  },

  listener: {
    port: 443,
    protocol: 'HTTPS',
    sslPolicy: 'ELBSecurityPolicy-TLS13-1-2-2021-06',
    certificateArn: cert.arn,
  },
});

I also tried forcing the certificate to stay in Pending validation state, but that gives me a different error: UnsupportedCertificate: The certificate 'REDACTED' must have a fully-qualified domain name, a supported signature, and a supported key size..

The only way I was able to replicate the same error message is by passing undefined for the certificateArn property of the listener. @dan-cooke What versions of awsx/aws are you using? Can you try reproducing this with the latest versions and also check if the certificate gets created correctly?

mjeffryes commented 6 months ago

@dan-cooke if you're still seeing this error can you give us more details to reproduce? or should we close it?

dan-cooke commented 6 months ago

@mjeffryes thanks for looking into this! After I tore everything down again and up a few times the issue just stopped happening. I’m not entirely sure what caused it- I’m 100% sure my cert was in the right region.

but let’s close it for now - I can reopen in future if I encounter it again