I think it's impossible to, in one deployment, cre...
# typescript
h
I think it's impossible to, in one deployment, create an SSL certificate and DNS entries to validate that certificate for a domain with multiple "subjectAlternativeNames" in a general way.
This snippet demonstrates the problem. To see the bug, set
SHOW_BUG
at the top to
true
. To see it work (but not general), set
SHOW_BUG
to
false
. In both cases, set an environment variable
APEX_DOMAIN
to a domain you control . Otherwise, it defaults to
<http://example.com|example.com>
which won't work for anybody:
Copy code
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";


const SHOW_BUG = true


const apex = process.env.APEX_DOMAIN || "<http://example.com|example.com>"
const cert = new aws.acm.Certificate("cert", {
  domainName: `v.${apex}`,
  subjectAlternativeNames: [`vv.${apex}`, `vvv.${apex}`],
  validationMethod: "DNS",
});


const zone = aws.route53.getZone({
  name: apex,
  privateZone: false,
});


if(SHOW_BUG) {
  const domains = cert.domainValidationOptions.apply((opts) => 
    opts.map((opt) => 
      new aws.route53.Record(opt.resourceRecordName, {
        name: opt.resourceRecordName,
        records: [opt.resourceRecordValue],
        ttl: 60,
        type: opt.resourceRecordType,
        zoneId: zone.id,
      }, { dependsOn: cert })
    )
  )


  new aws.acm.CertificateValidation(`cert-${apex}`, { 
    certificateArn: cert.arn,
    validationRecordFqdns: domains.apply((doms) => doms.map((dom) => dom.fqdn))
  }, { dependsOn: domains })
}
else {
  let domains: Array<aws.route53.Record> = []
  for(let i = 0; i < 3; i++) {
    domains.push(new aws.route53.Record(`val-${i}`, {
      name: cert.domainValidationOptions[i].resourceRecordName,
      records: [cert.domainValidationOptions[i].resourceRecordValue],
      ttl: 60,
      type: cert.domainValidationOptions[i].resourceRecordType,
      zoneId: zone.id,
    }, { dependsOn: cert }))
  }


  new aws.acm.CertificateValidation(`cert-${apex}`, { 
    certificateArn: cert.arn,
    validationRecordFqdns: domains.map((dom) => dom.fqdn)
  }, { dependsOn: domains })
}
Glad to make that a gist if it is easier
When the bug manifests, you get this output:
Copy code
> pulumi up
Previewing update (cert-demo):

     Type                    Name                 Plan       Info
 +   pulumi:pulumi:Stack     cert-demo-cert-demo  create     1 error; 4 messages
 +   └─ aws:acm:Certificate  cert                 create

Diagnostics:
  pulumi:pulumi:Stack (cert-demo-cert-demo):
    TypeError: Cannot read property 'concat' of undefined
        at C:\Users\Justin\Source\cert-demo\node_modules\@pulumi\pulumi\runtime\resource.js:356:29
        at Generator.next (<anonymous>)
        at fulfilled (C:\Users\Justin\Source\cert-demo\node_modules\@pulumi\pulumi\runtime\resource.js:18:58)

    error: Running program 'C:\Users\Justin\Source\cert-demo' failed with an unhandled exception:
    TypeError: Cannot read property 'concat' of undefined
        at C:\Users\Justin\Source\cert-demo\node_modules\@pulumi\pulumi\runtime\resource.js:356:29
        at Generator.next (<anonymous>)
        at fulfilled (C:\Users\Justin\Source\cert-demo\node_modules\@pulumi\pulumi\runtime\resource.js:18:58)
Notice there is no reference to
index.ts
in that stack trace, so pretty hard to figure out where this is coming from. However, is the
dependsOn
expression used when creating the
CertificateValidation
object .
w
This should work - and it looks like there may be a bug in the core Pulumi runtime library. Will take a look and open an issue if there is. Note that creating resources inside an apply is a little less ideal because it means previews may not be accurate (as we can’t know what will happen until the resource is actually created). Because of that - if the
donainValidationOptions
are always populated 1:1 with
subjectAlternateNames
then looping over the latter (which are known ahead of time) may be slightly better.
h
Thank you for taking a look. Probably there should be guidance in the docs or a better error message if nothing else. Glad to provide more details if needed!