Conditional use of ACM or IAM server certificate

620 views
Skip to first unread message

Trevor Robinson

unread,
Jan 3, 2017, 2:06:00 PM1/3/17
to Terraform
Hello,

I'm trying to migrate an existing AWS environment to Terraform. Some of our existing HTTPS certificates are in IAM and some are in ACM. (We plan to migrate to ACM as much as possible, except for Extended Validation certs, which must remain in IAM.) Whether a given domain cert is in IAM or ACM may also depend on the environment, such as production vs test/QA/staging. My question is whether there is a way to conditionally use an ACM cert if available, and fall back to an IAM cert if not, such that definitions of resources like load balancers can be shared across environments. For instance:


data "aws_iam_server_certificate" "my_cert" {
  name_prefix = "example.com"
  latest = true
}


data "aws_acm_certificate" "my_cert" {
  domain = "example-test.com"
}

common/my_elb.tf:

resource "aws_elb" "my_elb" {
  name = "example-elb"
  listener {
    instance_port = 80
    instance_protocol = "http"
    lb_port = 443
    lb_protocol = "https"
    ssl_certificate_id = "${data.???.my_cert.arn}"
  }
}

In this case, "???" could be either "aws_iam_server_certificate" or "aws_acm_certificate" depending on the environment. Is there some technique I could use to allow the definition of my_elb to use either type of cert? null_data_source seems to work, but I'm wondering if there's anything more concise.

append to prod/my_cert.tf:

data "null_data_source" "cert_arns" {
  inputs = {
    my_cert = "${data.aws_iam_server_certificate.my_cert.arn}"
  }
}

append to test/my_cert.tf:

data "null_data_source" "cert_arns" {
  inputs = {
    my_cert = "${data.aws_acm_certificate.my_cert.arn}"
  }
}

common/my_elb.tf:

    ssl_certificate_id = "${data.null_data_source.cert_arns.my_cert}"

Thanks,
Trevor

Bruno Giorgini

unread,
Oct 17, 2017, 10:29:23 PM10/17/17
to Terraform
Hey Trevor, I'm having exactly the same situation. How did you finally fixed the issue? Could you please post your snippet? Thanks!

Trevor Robinson

unread,
Oct 17, 2017, 11:43:00 PM10/17/17
to Terraform
We ended up importing all of our certs into ACM. But independent of that, we use the null_data_source technique with conditional inclusion based on directories. For example, "qa/*" in included in the QA environment, whereas "prod/*" is included in production. ("*" is included for all environments.) A wrapper script (which mainly calls make) copies all the relevant files to a working directory used by Terraform. Then we have the following files:


data "aws_acm_certificate" "domain1_wildcard" {
  domain = "*.domain1.com"
}

data "aws_acm_certificate" "domain2" {
  domain = "domain2.com"
}

data "null_data_source" "cert_arn" {
  inputs = {
    service1 = "${data.aws_acm_certificate.domain1_wildcard.arn}"
    service2 = "${data.aws_acm_certificate.domain2.arn}"
    # ...
  }
}


data "aws_acm_certificate" "domain1_wildcard" {
  domain = "*.qa.domain1.com"
}

data "aws_acm_certificate" "domain2" {
  domain = "qa.domain2.com"
}

data "null_data_source" "cert_arn" {
  inputs = {
    service1 = "${data.aws_acm_certificate.domain1_wildcard.arn}"
    service2 = "${data.aws_acm_certificate.domain2.arn}"
    # ...
  }
}

The wrapper script picks up only the appropriate version of cert_arn.tf for the environment. Then we can just use things like certificate_arn = "${data.null_data_source.cert_arn.inputs.service1}" in our common resources. Obviously, I'm showing all ACM certs, but IAM certs should work as well.

If you don't want a wrapper script that assembles files depending on environment, you can use the conditional interpolation expressions in newer versions of Terraform to select the correct cert resource and make the cert resources themselves conditional using the count attribute.

-Trevor
Reply all
Reply to author
Forward
0 new messages