hashicorp / terraform-provider-aws

The AWS Provider enables Terraform to manage AWS resources.
https://registry.terraform.io/providers/hashicorp/aws
Mozilla Public License 2.0
9.74k stars 9.09k forks source link

[Bug]: aws_acm_certificate error "certificate field contains more than one certificate" #37537

Open reskin89 opened 3 months ago

reskin89 commented 3 months ago

Terraform Core Version

1.6.6

AWS Provider Version

5.49.0

Affected Resource(s)

aws_acm_certificate resource is provided either a single line escaped string, or a file() call to a pem encoded certificate, returns the following error when importing a certificate:

api error ValidationException: The certificate field contains more than one certificate. You can specify only one certificate in this field.

This error is also returned when private_key and certificate_body are both empty strings, denoting a deeper issue afoot.

Expected Behavior

The ACM Certificate should be imported int AWS ACM.

Actual Behavior

An error stating I've provided multiple certificates when I have not.

Relevant Error/Panic Output Snippet

2024-05-15T15:11:46.359Z [ERROR] vertex "aws_acm_certificate.cert" error: importing ACM Certificate: operation error ACM: ImportCertificate, https response error StatusCode: 400, RequestID: 0ed51563-f2bf-40b7-9277-2f655896912d, api error ValidationException: The certificate field contains more than one certificate. You can specify only one certificate in this field.

This is the only error in the debug, its coming back from AWS but I'm wondering how its getting to AWS improperly.

Terraform Configuration Files

resource "aws_acm_certificate" "cert" {
  private_key       = var.private_key
  certificate_body  = var.certificate_body
  certificate_chain = var.certificate_chain
}

have also attempted writing them to files like so:

resource "aws_acm_certificate" "cert" {
  private_key       = file("./key.pem")
  certificate_body  = file("./cert.pem")
  certificate_chain = file("./chain.pem")
}

Steps to Reproduce

Import an SSL certificate via the aws_acm_certificate resource

Debug Output

2024-05-15T15:11:46.359Z [ERROR] vertex "aws_acm_certificate.cert" error: importing ACM Certificate: operation error ACM: ImportCertificate, https response error StatusCode: 400, RequestID: 0ed51563-f2bf-40b7-9277-2f655896912d, api error ValidationException: The certificate field contains more than one certificate. You can specify only one certificate in this field.

Panic Output

No response

Important Factoids

No response

References

No response

Would you like to implement a fix?

None

github-actions[bot] commented 3 months ago

Community Note

Voting for Prioritization

Volunteering to Work on This Issue

reskin89 commented 3 months ago

As an added note, I am able to import this certificate via both the AWS console, and the aws cli, using the same strings and files without an issue.

justinretzolk commented 3 months ago

Hey @reskin89 👋 Thank you for taking the time to raise this! Are you able to supply a bit more of the debug logging over, redacted as needed? Having a bit more context (specifically around the request/response) may reveal the underlying issue.

reskin89 commented 3 months ago

@justinretzolk what I provided is all the debug I have regarding the acm request, its very sparse.

j-fraga commented 3 months ago

Today I wasted a few hours trying to find out what was wrong with my Terraform code. I kept receiving the same error:

ValidationException: The certificate field contains more than one certificate. You can specify only one certificate in this field.

My value of certificate_body is a valid certificate. Just one certificate.

I'm running AWS provider v5.50.0 with Terraform v1.8.1

j-fraga commented 3 months ago

It appears that the issue is not with the terraform-provider-aws but with the ACM API itself, which can be quite particular. If you take a PEM certificate and remove all line breaks, ACM might (and I emphasize might) not accept it. This issue can occur even when importing a certificate using the AWS Console.

The workaround I found to ensure ACM accepts all certificates involves using Base64 encoding/decoding:

  1. Generate a Base64-encoded version of the PEM file using a command-line tool. After that, you can remove the line breaks from the Base64-encoded file and store it in Secrets Manager, for example. This won't corrupt the Base64-encoded content of the file.
  2. Use the Terraform function base64decode on each argument value within the aws_acm_certificate resource block that accepts certificates or private keys. Example:
resource "aws_acm_certificate" "certificate" {
  certificate_body  = base64decode(var.base64_encoded_certificate_body)
  private_key       = base64decode(var.base64_encoded_var_private_key)
  certificate_chain = base64decode(var.base64_encoded_var_certificate_chain)
}

Base64 is designed to transmit binary data across channels that only reliably support text, making it particularly useful in this ACM scenario.

reskin89 commented 3 months ago

Hmmm, seems like something that should be in the docs or handled by the provider.

I'll try to make a docs PR, I can't imagine I'm the only one that's encountered this however, the fact that I could take the same file contents in the AWS console and via the AWS CLI (which uses the api under the hood anyway) didn't have an issue, which is why I think there may be something extra the provider did that damaged the format

j-fraga commented 3 months ago

In my case, not even the AWS Console was accepting my PEM file! And regarding the AWS CLI, the fact the docs explicitly say you must use fileb:// instead of file:// indicates the certificate should be handled as binary data.

A docs PR would be great!