Terraform-provider-aws: "Resource" to sign aws_acmpca_certificate_authority with

Created on 14 Aug 2018  路  7Comments  路  Source: hashicorp/terraform-provider-aws

Community Note

  • Please vote on this issue by adding a 馃憤 reaction to the original issue to help the community and maintainers prioritize this request
  • Please do not leave "+1" or "me too" comments, they generate extra noise for issue followers and do not help prioritize the request
  • If you are interested in working on this issue or have submitted a pull request, please leave a comment

Description

Currently, the aws_acmpca_certificate_authority resource exists (thanks @bflad) but it leaves the CA in an unusable state, pending a signature from a parent CA of some sort. Right now we have to go inject that signed certificate ourselves and then the ACM PCA is usable. Having a terraform "virtual resource" for this process would streamline this process because then we can just rerun terraform.

Furthermore, for testing, we could also use terraform's nice TLS module to sign the ACMPCA CSR automatically as part of the workflow, and then proceed for example to generate certificates with something like @TFaga's https://github.com/terraform-providers/terraform-provider-aws/issues/5550.

New or Affected Resource(s)

  • aws_acmpca_certificate_authority_signature (I don't know what to call it, really)

Potential Terraform Configuration

resource "aws_acmpca_certificate_authority" "pca" {
  ...
}

resource "tls_locally_signed_cert" "test-zomg" {
  cert_request_pem   = "${aws_acmpca_certificate_authority.pca.certificate_signing_request}"
  ...
}

resource "aws_acmpca_certificate_authority_signature" "sig" {
  certificate = "${tls_locally_signed_cert.test-zomg.cert_pem}"
}
new-resource servicacmpca

Most helpful comment

@sarkis
Thanks, that's what I ended up doing. I found out you also need to manually set the permissions on the CA once the cert is imported as well:

resource "null_resource" "private_root_ca_import" {
  provisioner "local-exec" {
    command = <<EOT
    aws acm-pca import-certificate-authority-certificate \
      --certificate-authority-arn ${aws_acmpca_certificate_authority.private_ca.arn} \
      --certificate '${tls_locally_signed_cert.private_ca_cert.cert_pem}' \
      --certificate-chain '${tls_self_signed_cert.private_root_ca_cert.cert_pem}'
    EOT
  }

  provisioner "local-exec" {
    command = <<EOT
    aws acm-pca create-permission \
      --certificate-authority-arn ${aws_acmpca_certificate_authority.private_ca.arn} \
      --principal 'acm.amazonaws.com' \
      --source-account '${data.aws_caller_identity.current.account_id}' \
      --actions 'IssueCertificate' 'GetCertificate' 'ListPermissions'
    EOT
  }
}

All 7 comments

For what its worth, the ACMPCA SDK refers to this as the "Certificate Authority Certificate" so we would likely prefer to match the upstream naming.

Looking at the SDK call, it seems we will need to support three arguments:

resource "aws_acmpca_certificate_authority_certificate" "example" {
  certificate_authority_arn = "${aws_acmpca_certificate_authority.example.arn}"
  certificate = ""
  certificate_chain = ""
}

Yeah, I was telling myself that's what the actual issued certificate resources were gonna be called but I guess those would more likely be aws_acmpca_certificate.

One potential weirdness is the deletion behavior of this resource, because I don't think ACM PCA lets you "decertify" a PCA, so resource deletion would likely be a no-op.

How are others currently handling activating their AWS CAs with Terraform until this issue is resolved?

@CharlieC3 I think an option here would be to use a null resource with localexec and running the aws acm-pca import-certificate-authority-certificate command via the cli.

@sarkis
Thanks, that's what I ended up doing. I found out you also need to manually set the permissions on the CA once the cert is imported as well:

resource "null_resource" "private_root_ca_import" {
  provisioner "local-exec" {
    command = <<EOT
    aws acm-pca import-certificate-authority-certificate \
      --certificate-authority-arn ${aws_acmpca_certificate_authority.private_ca.arn} \
      --certificate '${tls_locally_signed_cert.private_ca_cert.cert_pem}' \
      --certificate-chain '${tls_self_signed_cert.private_root_ca_cert.cert_pem}'
    EOT
  }

  provisioner "local-exec" {
    command = <<EOT
    aws acm-pca create-permission \
      --certificate-authority-arn ${aws_acmpca_certificate_authority.private_ca.arn} \
      --principal 'acm.amazonaws.com' \
      --source-account '${data.aws_caller_identity.current.account_id}' \
      --actions 'IssueCertificate' 'GetCertificate' 'ListPermissions'
    EOT
  }
}

@CharlieC3 I think an option here would be to use a null resource with localexec and running the aws acm-pca import-certificate-authority-certificate command via the cli.

alternative workaround if you want to install a Type = ROOT ca cert, using some dummy example values

(this is the same way that the console GUI does it if you choose "install ca cert" after creating the PCA - I checked the API calls it makes with dev tools)

...
  type = "ROOT"

  provisioner "local-exec" {
    command = <<EOT
      export PCA_ARN="${aws_acmpca_certificate_authority.pca.arn}"
      export PCA_CSR="${aws_acmpca_certificate_authority.pca.certificate_signing_request}"
      export VALIDITY_DAYS=3650
      ${path.module}/scripts/activate-root-pca.sh
    EOT
  }
#activate-root-pca.sh
ROOT_CA_CERT_ARN=$(aws acm-pca issue-certificate \
  --certificate-authority-arn "$PCA_ARN" \
  --csr "$PCA_CSR" \
  --signing-algorithm SHA256WITHRSA \
  --validity "Value=$VALIDITY_DAYS,Type=\"DAYS\"" \
  --template-arn "arn:aws:acm-pca:::template/RootCACertificate/V1" \
  --output json \
  | jq -r '.CertificateArn')

sleep 10

ROOT_CA_CERT=$(aws acm-pca get-certificate \
  --certificate-authority-arn "$PCA_ARN" \
  --certificate-arn "$ROOT_CA_CERT_ARN" \
  --output json \
  | jq -r '.Certificate' \
  | sed 's/\\n/\n/g') # swap literal newline characters for newlines

aws acm-pca import-certificate-authority-certificate \
  --certificate-authority-arn "$PCA_ARN" \
  --certificate "$ROOT_CA_CERT"

needless to say, I'm hopeful to see https://github.com/terraform-providers/terraform-provider-aws/pull/13684 etc. get merged :)

Ran into this issue https://github.com/aws/aws-cli/issues/5011 when trying the above approach.

Went with this instead:

resource "aws_acmpca_certificate_authority" "example" {

  provisioner "local-exec" {
    command     = "./activate-pca.sh --common-name '${local.ca_root_name}'"
    interpreter = ["/bin/bash"]
  }

  certificate_authority_configuration {
    key_algorithm     = "RSA_4096"
    signing_algorithm = "SHA512WITHRSA"

    subject {
      common_name         = local.ca_root_name
    }
}

./activate-pca.sh

# Skipping arg parsing
CA_ARN=$(
    aws acm-pca list-certificate-authorities \
      --output text \
      --query "CertificateAuthorities[?CertificateAuthorityConfiguration.Subject.CommonName==\`${COMMON_NAME}\`].Arn"
)

CA_INFO=$(aws acm-pca describe-certificate-authority --certificate-authority-arn "$CA_ARN")
CA_STATUS=$(echo "$CA_INFO" | jq -r '.CertificateAuthority.Status')

if [[ "$CA_STATUS" != "PENDING_CERTIFICATE" ]]; then
  echo "Error: CA is '$CA_STATUS', cannot activate"
  exit 1
fi

CA_CSR=$(
  aws acm-pca get-certificate-authority-csr \
    --certificate-authority-arn "${CA_ARN}" \
    --output text
)

and then as the above example.

Was this page helpful?
0 / 5 - 0 ratings