terraform-provider-azurerm icon indicating copy to clipboard operation
terraform-provider-azurerm copied to clipboard

Unable to create key vault certificate. Reports invalid PKCS#12 format

Open anuradhaarao opened this issue 3 years ago β€’ 5 comments

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

Terraform (and AzureRM Provider) Version

Affected Resource(s)

  • azurerm_key_vault_certificate

Terraform Configuration Files

resource "azurerm_key_vault_certificate" "certificate" {
  name         = "wildcard-${local.certificate_name}" #replaces dot with dashes.
  key_vault_id = module.key_vault.key_vault_id
  depends_on = [module.key_vault.terraform_managed_identity_policy]
  certificate {
    contents = data.azurerm_key_vault_secret.cert.value
    password = data.azurerm_key_vault_secret.cert_password.value
  }
  certificate_policy {
    issuer_parameters {
      name = "Unknown"
    }
    key_properties {
      exportable = true
      key_size   = 2048
      key_type   = "RSA"
      reuse_key  = false
    }
    secret_properties {
      content_type = "application/x-pkcs12"
    }
  }
}

Expected Behaviour

resource successfully created

Actual Behaviour

keyvault.BaseClient#ImportCertificate: Failure responding to request: StatusCode=400 -- Original Error: autorest/azure: Service returned an error. Status=400 Code="BadParameter" Message="The specified PKCS#12 X.509 certificate content can not be read. Please check if certificate is in valid PKCS#12 format."

Steps to Reproduce

  1. terraform apply

Important Factoids

  1. pfx certificate is stored in another azure keyvault as a secret, which is being used to create this certificate
  2. Import of pfx using secret and password stored in keyvault checks out

References

anuradhaarao avatar Mar 21 '22 16:03 anuradhaarao

Hi @anuradhaarao According to the error message, looks like the cert content is not in correct format. There is one possibility I could think of is the format is application/x-pem-file, maybe you can give it a try.

myc2h6o avatar Mar 23 '22 15:03 myc2h6o

@myc2h6o - The secret is base64encoded pfx value too, and using powershell I can confirm that this can be imported as a pfx file successfully. But I am not able to do the same thing through terraform and was wondering if any additional parameters are required.

anuradhaarao avatar Mar 23 '22 20:03 anuradhaarao

Hi @anuradhaarao Since it's probably not possible to share the cert, I'm sharing what I've done which can generate the cert successfully. Hope this could help you troubleshoot the issue.

Terraform version: v1.1.5 AzureRM provider version: v2.99.0

I used below command to generate a cert: New-SelfSignedCertificate -DnsName "www.contoso.com" -CertStoreLocation "cert:\LocalMachine\My"

Thumbprint                                Subject
----------                                -------
0557CBA10E47B975532B453918285777855F04D6  CN=www.contoso.com

And export to pfx with the password: $CertPassword = ConvertTo-SecureString -String "123456" -Force -AsPlainText; Export-PfxCertificate -Cert cert:\LocalMachine\My\0557CBA10E47B975532B453918285777855F04D6 -FilePath C:\test.pfx -Password $CertPassword

Then convert it to base64 string: [Convert]::ToBase64String([IO.File]::ReadAllBytes("C:\test.pfx")) > base64pfx.txt

I then stored the output from base64pfx.txt and the password 123456 to Azure Key Vault Secrets. After that, I'm able to create the cert with the config file you shared (with module.key_vault.key_vault_id updated to my key vault id and depends_on removed)

You mentioned you are able to import the cert using PowerShell, maybe there is some different validation between the Azure API called by PowerShell and Terraform. For Terraform, you can set environment variable TF_LOG to DEBUG (https://www.terraform.io/internals/debugging) to see the API request detail, it may have some useful info which you can compare with the property values of certificate created from PowerShell

myc2h6o avatar Mar 24 '22 07:03 myc2h6o

Unfortunately I get the same error as @anuradhaarao with the certificate in pfx format. But for me the error only occurs when I run terraform apply in my Gitlab-CI (ubuntu:jammy). As soon as I run the same command from my Mac laptop, I didnt get the error. Manually I also can import the same certificate successfully in Azure KeyVault.

In the Gitlab-CI my Ubuntu Image uses the Terraform version: v1.2.4 and the AzureRM provider version: v3.11.0. Locally I use the Terraform version: v1.1.8.

yanehi avatar Jul 06 '22 15:07 yanehi

@yanehi sorry for the late reply. The error StatusCode=400 -- Original Error: autorest/azure: Service returned an error. Status=400 Code="BadParameter" Message="The specified PKCS#12 X.509 certificate content can not be read. Please check if certificate is in valid PKCS#12 format." is returned from the service side so probably the generated request body is different in these two environments. Since it's running fine on your Mac but not on the Gitlab-CI, would you mind turn on the Debug logging as mentioned at https://www.terraform.io/internals/debugging to see the API request detail, it may help with the troubleshooting.

myc2h6o avatar Sep 23 '22 04:09 myc2h6o

I have the same issue in importing a pfx/pem file through Terraform, getting the same error message. I tried setting the TF_LOG environment variable to TRACE, however, it didn't produce any additional log output for Terraform. I also tried importing the same cert directly through the portal: this was successful. I also tried importing the same certificate through az cli statement, this also failed. Here I did get debug output:

az keyvault certificate import --vault-name "kv_name" -n "ExampleCertificate" -f "C:/Users/myname/OneDrive - Microsoft/Personal/star_myname_com/wildcard_myname_com.pfx" --debug ←[36mcli.knack.cli: Command arguments: ['keyvault', 'certificate', 'import', '--vault-name', 'kv_name', '-n', 'ExampleCertificate', '-f', 'C:/Users/myname/OneDrive - Microsoft/Personal/star_myname_com/wildcard_myname_com.pfx', '--debug']←[0m ←[36mcli.knack.cli: init debug log: Enable color in terminal.←[0m ←[36mcli.knack.cli: Event: Cli.PreExecute []←[0m ←[36mcli.knack.cli: Event: CommandParser.OnGlobalArgumentsCreate [<function CLILogging.on_global_arguments at 0x0352BD60>, <function OutputProducer.on_global_arguments at 0x0371E6A0>, <function CLIQuery.on_global_arguments at 0x037312F8>]←[0m

←[36mcli.knack.cli: Event: CommandInvoker.OnPreCommandTableCreate []←[0m ←[36mcli.azure.cli.core: Modules found from index for 'keyvault': ['azure.cli.command_modules.keyvault']←[0m ←[36mcli.azure.cli.core: Loading command modules:←[0m ←[36mcli.azure.cli.core: Name Load Time Groups Commands←[0m ←[36mcli.azure.cli.core: keyvault 0.081 20 122←[0m ←[36mcli.azure.cli.core: Total (1) 0.081 20 122←[0m ←[36mcli.azure.cli.core: These extensions are not installed and will be skipped: ['azext_ai_examples', 'azext_next']←[0m ←[36mcli.azure.cli.core: Loading extensions:←[0m ←[36mcli.azure.cli.core: Name Load Time Groups Commands Directory←[0m ←[36mcli.azure.cli.core: Total (0) 0.000 0 0 ←[0m ←[36mcli.azure.cli.core: Loaded 20 groups, 122 commands.←[0m ←[36mcli.azure.cli.core: Found a match in the command table.←[0m ←[36mcli.azure.cli.core: Raw command : keyvault certificate import←[0m ←[36mcli.azure.cli.core: Command table: keyvault certificate import←[0m ←[36mcli.knack.cli: Event: CommandInvoker.OnPreCommandTableTruncate [<function AzCliLogging.init_command_file_logging at 0x042A1F10>]←[0m ←[36mcli.azure.cli.core.azlogging: metadata file logging enabled - writing logs to 'C:\Users\myname.azure\commands\2022-10-07.08-30-36.keyvault_certificate_import.11848.log'.←[0m ←[32maz_command_data_logger: command args: keyvault certificate import --vault-name {} -n {} -f {} --debug←[0m ←[36mcli.knack.cli: Event: CommandInvoker.OnPreArgumentLoad [<function register_global_subscription_argument..add_subscription_parameter at 0x042DCEC8>]←[0m ←[36mcli.knack.cli: Event: CommandInvoker.OnPostArgumentLoad []←[0m ←[36mcli.knack.cli: Event: CommandInvoker.OnPostCommandTableCreate [<function register_ids_argument..add_ids_arguments at 0x042DCFA0>, <function register_cache_arguments..add_cache_arguments at 0x04306538>]←[0m ←[36mcli.knack.cli: Event: CommandInvoker.OnCommandTableLoaded []←[0m ←[36mcli.knack.cli: Event: CommandInvoker.OnPreParseArgs []←[0m ←[36mcli.knack.cli: Event: CommandInvoker.OnPostParseArgs [<function OutputProducer.handle_output_argument at 0x0371E6E8>, <function CLIQuery.handle_query_parameter at 0x03731340>, <function register_ids_argument..parse_ids_arguments at 0x043064F0>]←[0m ←[36mmsrest.universal_http.requests: Configuring retry: max_retries=4, backoff_factor=0.8, max_backoff=90←[0m ←[36mcli.azure.cli.core.util: azure.cli.core.util.handle_exception is called with an exception:←[0m ←[36mcli.azure.cli.core.util: Traceback (most recent call last): File "D:\a\1\s\build_scripts\windows\artifacts\cli\Lib\site-packages\azure/cli/command_modules/keyvault/custom.py", line 1622, in import_certificate File "D:\a\1\s\build_scripts\windows\artifacts\cli\Lib\site-packages\OpenSSL/crypto.py", line 3067, in load_pkcs12
File "D:\a\1\s\build_scripts\windows\artifacts\cli\Lib\site-packages\OpenSSL/_util.py", line 54, in exception_from_error_queue OpenSSL.crypto.Error: [('PKCS12 routines', 'PKCS12_parse', 'mac verify failure')]

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File "D:\a\1\s\build_scripts\windows\artifacts\cli\Lib\site-packages\azure/cli/command_modules/keyvault/_command_type.py", line 112, in keyvault_command_handler File "D:\a\1\s\build_scripts\windows\artifacts\cli\Lib\site-packages\azure/cli/command_modules/keyvault/custom.py", line 1626, in import_certificate knack.util.CLIError: We could not parse the provided certificate as .pem or .pfx. Please verify the certificate with OpenSSL.

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File "D:\a\1\s\build_scripts\windows\artifacts\cli\Lib\site-packages\knack/cli.py", line 231, in invoke File "D:\a\1\s\build_scripts\windows\artifacts\cli\Lib\site-packages\azure/cli/core/commands/init.py", line 663, in execute File "D:\a\1\s\build_scripts\windows\artifacts\cli\Lib\site-packages\azure/cli/core/commands/init.py", line 726, in _run_jobs_serially File "D:\a\1\s\build_scripts\windows\artifacts\cli\Lib\site-packages\azure/cli/core/commands/init.py", line 697, in _run_job File "D:\a\1\s\build_scripts\windows\artifacts\cli\Lib\site-packages\azure/cli/core/commands/init.py", line 333, in call File "D:\a\1\s\build_scripts\windows\artifacts\cli\Lib\site-packages\azure/cli/command_modules/keyvault/_command_type.py", line 138, in keyvault_command_handler File "D:\a\1\s\build_scripts\windows\artifacts\cli\Lib\site-packages\azure/cli/command_modules/keyvault/command_type.py", line 51, in keyvault_exception_handler knack.util.CLIError: We could not parse the provided certificate as .pem or .pfx. Please verify the certificate with OpenSSL. ←[0m ←[91mcli.azure.cli.core.azclierror: We could not parse the provided certificate as .pem or .pfx. Please verify the certificate with OpenSSL.←[0m ←[91maz_command_data_logger: We could not parse the provided certificate as .pem or .pfx. Please verify the certificate with OpenSSL.←[0m ←[36mcli.knack.cli: Event: Cli.PostExecute [<function AzCliLogging.deinit_cmd_metadata_logging at 0x042A4070>]←[0m
←[32maz_command_data_logger: exit code: 1←[0m ←[32mcli.main: Command ran in 6.951 seconds (init: 3.745, invoke: 3.206)←[0m ←[32mtelemetry.save: Save telemetry record of length 3065 in cache←[0m ←[32mtelemetry.check: Returns Positive.←[0m ←[32mtelemetry.main: Begin creating telemetry upload process.←[0m ←[32mtelemetry.process: Creating upload process: "C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\python.exe C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\Lib\site-packages\azure\cli\telemetry_init
.pyc C:\Users\myname.azure"←[0m
←[32mtelemetry.process: Return from creating process←[0m ←[32mtelemetry.main: Finish creating telemetry upload process.←[0m

My Terraform environment is running in a GH codespace, there I have versions:

  • TF: 1.3.1
  • az cli: 2.40.0

I tried the upload both on from Linux (GH codespace using debian) and from my local laptop, both failing with the same error.

So summing up:

  • TF: fail
  • Portal: success
  • az cli: fail

vermegi avatar Oct 07 '22 07:10 vermegi

Update: I was able to import the certificate with az cli, by specifying the password as an extra parameter: az keyvault certificate import --vault-name "kv_name" -n "ExampleCertificate" -f "../wildcard_myname_com.pfx" --password $CERT_PASSWORD

The same with TF is still failing though. Relevant TF part: resource "azurerm_key_vault_certificate" "uploaded_cert" { count = var.use_self_signed_cert ? 0 : 1 name = var.cert_name key_vault_id = azurerm_key_vault.kv.id

certificate { contents = filebase64(var.cert_path) password = var.cert_password } }

Error message: Message="The specified PKCS#12 X.509 certificate content can not be read. Please check if certificate is in valid PKCS#12 format."

Happy to try out the TF logging, if someone can give me pointers on how to set it up TF_LOG=TRACE did not work for me.

vermegi avatar Oct 07 '22 07:10 vermegi

So, I fixed the issue now in my TF as well. Took me a null_resource with local_exec to execute the az cli directly. This also outputted the password I was using for the certificate, and with this, quotes do matter!

My plan statement that now makes my apply work:

terraform plan -var-file="myvars.tfvars" -out=plan.tfplan -var='git_repo_passwords=["$GIT_REPO_PASSWORD","$GIT_REPO_PASSWORD"]' -var="cert_password=$CERT_PASSWORD"

Mind the quotes!

vermegi avatar Oct 07 '22 11:10 vermegi

@vermegi thanks for sharing the experience. setting TF_LOG to DEBUG shall give you the API request details.

myc2h6o avatar Nov 14 '22 06:11 myc2h6o