crossplane-contrib / provider-jet-aws

AWS Provider for Crossplane that is built with Terrajet.
https://crossplane.io
Apache License 2.0
37 stars 30 forks source link

AWS Certificate requires X.509 certificate body and CA chain to be specified individually #242

Open grafanalf opened 1 year ago

grafanalf commented 1 year ago

What problem are you facing?

While I understand that the Terrajet AWS provider mimics the AWS API, I have a use case in which I would need that the X.509 certificate body and the CA chain to be specified as a single attribute, that is, as a base64-encoded PEM blob. Looking at https://doc.crds.dev/github.com/crossplane-contrib/provider-jet-aws/acm.aws.jet.crossplane.io/Certificate/v1alpha1@v0.5.0-preview, confirms that: the Certificate object states that certificateBody and certificateChain are both mandatory.

I have a prototype of a Crossplane composition that allows fetching an X.509 certificate provisioned by cert-manager stored in a Secret, and uploads it to AWS. At the moment, I am using Crossplane's Terraform provider because of what I said previously. I could use the Terrajet AWS provider only if it supports the certificate body and CA chain to be specified in a single attribute.

The Terrajet AWS code could detect this condition: if the certificate body consists of multiple certificate blocks, it can take the first block as the certificate body, and the remaining as the CA chain. This is what I am currently doing in plain Terraform:

variable "private_key" {
  description = "PEM-encoded private key"
  type        = string
}
variable "certificate_chain" {
  description = "PEM-encoded certificate chain"
  type        = string
}
locals {
  private_key = base64decode(var.private_key)
  certificates = base64decode(var.certificate_chain)
  split_certificates = split(
    "-----END CERTIFICATE-----",
    local.certificates
  )
  certificate_body = trimspace(
    format(
      "%s-----END CERTIFICATE-----",
      local.split_certificates[0]
    )
  )
  split_certificate_chain = slice(
    local.split_certificates,
    1,
    length(local.split_certificates) - 1
  )
  certificate_chain = trimspace(
    format(
      "%s-----END CERTIFICATE-----",
      join("-----END CERTIFICATE-----", local.split_certificate_chain)
    )
  )
}
resource "aws_acm_certificate" "cert" {
  private_key       = local.private_key
  certificate_body  = local.certificate_body
  certificate_chain = local.certificate_chain
}

How could Crossplane help solve your problem?

By having the Terrajet AWS provider allow the CA chain to be an optional argument, and detect when the certificate body is a multi-part base64-encoded PEM blob and, in that case, perform the split that I implemented above in Terraform.