Rsadecrypt function giving Error with valid ciphertext string

Terraform Version

Terraform v0.15.0-beta2
on linux_amd64
+ provider registry.terraform.io/hashicorp/aws v3.33.0
+ provider registry.terraform.io/hashicorp/local v2.1.0
+ provider registry.terraform.io/hashicorp/null v3.1.0
+ provider registry.terraform.io/hashicorp/template v2.2.0

Terraform Configuration Files

located here:
https://github.com/surfd4wg/terraform_rsadecrypt_debug 

Debug Output

terraform.log located here:

Crash Output

terraform init - passes.
terraform plan - Error: Invalid Function Argument

│ on outputs.tf line 20, in output “Admin_Password_rsadecrypted”:
│ 20: value = rsadecrypt(aws_instance.winrm.*.password_data, file(var.private_key_path))
│ ├────────────────
│ │ aws_instance.winrm is tuple with 2 elements

│ Invalid value for “ciphertext” parameter: string required.

Expected Behavior

The output of Admin_Password_rsadecrypted should be the decrypted password. This works without the count variable in the aws_instance block in main.tf. Adding the .*. to Admin_Password_rsadecrypted causes it to Error. If I have count = 2 Windows Servers, I would expect the output to display the Windows Administrator password for both servers.

Actual Behavior

Invalid ciphertext error message.

Steps to Reproduce

Please list the full steps required to reproduce the issue, for example:

  1. terraform init
  2. terraform plan
    also, if you comment out the Admin_Password_decrypted line in outputs.tf, you will see that Admin_Password outputs the correct base64 encoded string.

Additional Context

Because Admin_Password outputs the correct base64 string, I believe adding the .*. for the count variable, somehow causes rsadecrypt to not accept the value.

References

Originally posted as a bug, but was asked to redirect to this community.

Looking for help.
Thank you

Hi @surfd4wg,

This error message is telling you that aws_instance.winrm.*.password_data is not a suitable argument for rsadecrypt, because that argument expects a string.

This aws_instance.winrm.*.password_data expression is a splat expression, and so its result will be a list of whatever type the password_data attribute has. From the provider’s docs I see that password_data is a string, and so this value is a list of strings, not just a single string.

You mentioned under “Expected Behavior” that your goal here is to show the decrypted data for each of the instances of aws_instance.winrm. To get that result, you can use a for expression to apply the rsadecrypt function to each of the instances in turn, making the output value itself be a list of strings:

output "admin_passwords_decrypted" {
  value = [
    for inst in aws_instance.winrm : rsadecrypt(inst.password_data, file(var.private_key_path))
  ]
}

As noted in the splat expression documentation, a splat expression is effectively a shorthand for a for expression for the common situation of just taking the values of a particular attribute on all of the objects in a list. However, since you want to apply rsadecrypt to each of them you’ve exceeded the capabilities of the shorthand and so you need to switch to using a full for expression, like I’ve shown above.


If you implement the above then you might encounter another error message, if the provider has marked this password_data attribute has having a sensitive value. In that case, Terraform requires that you also mark the output value as sensitive, so that the secret won’t get exposed in cleartext in the UI:

output "admin_passwords_decrypted" {
  value = [
    for inst in aws_instance.winrm : rsadecrypt(inst.password_data, file(var.private_key_path))
  ]
  sensitive = true
}

With that extra setting, Terraform will hide the exact values when it prints the output values to the terminal, although you can still get the secret strings in cleartext as JSON if you want to retrieve it as part of integrating with some other software that needs these passwords:

terraform output -json admin_passwords_decrypted