Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

aws_key_pair forces new resource after importing #1092

Closed
iserko opened this issue Jul 10, 2017 · 14 comments · May be fixed by #40075
Closed

aws_key_pair forces new resource after importing #1092

iserko opened this issue Jul 10, 2017 · 14 comments · May be fixed by #40075
Labels
bug Addresses a defect in current functionality. service/ec2 Issues and PRs that pertain to the ec2 service.

Comments

@iserko
Copy link

iserko commented Jul 10, 2017

Terraform Version

Terraform v0.9.11

Affected Resource(s)

  • aws_key_pair

Terraform Configuration Files

resource "aws_key_pair" "igor" {
  key_name = "igor_20150712"
  public_key = "${file("igor_20150712.pub")}"
}

Expected Behavior

After using terraform import aws_key_pair.igor igor_20150712 I would have expected a terraform plan to not result in any changes.

Actual Behavior

Got

-/+ aws_key_pair.igor
    fingerprint: "REDACTED" => "<computed>"
    key_name:    "igor_20150712" => "igor_20150712"
    public_key:  "" => "ssh-rsa AAAAREDACTED" (forces new resource)

Steps to Reproduce

  1. terraform import aws_key_pair.igor
  2. terraform plan -target aws_key_pair.igor

Workaround

Manually adding a public_key section into terraform.tfstate. Changing:

"attributes": {
    "fingerprint": "REDACTED",
    "id": "igor_20150712",
    "key_name": "igor_20150712"
},

to

"attributes": {
    "fingerprint": "REDACTED",
    "id": "igor_20150712",
    "key_name": "igor_20150712",
    "public_key": "ssh-rsa AAAAREDACTED"
},

resulted in no changes detected in the next terraform plan.

@stack72 stack72 added the bug Addresses a defect in current functionality. label Jul 10, 2017
@recurrence
Copy link

I don't believe AWS exposes the public_key via their API calls. I suppose an instance could be launched and then the key retrieved but I suspect that is out of scope at the moment. Plus it would be strictly better if AWS exposed this information.

@Ninir
Copy link
Contributor

Ninir commented Aug 21, 2017

Hey folks,

As @recurrence exposed it, the public_key attribute isn't returned by AWS. Terraform simply trims the key for normalization, but the attribute is set in the state and never set again, excepted when the user attribute changes.

@iserko As AWS does not provide this information when using the API, there is nothing Terraform can help on that... 😞
If you import your configuration, you should set your public_key manually. In order to retrieve it, you can still generate it from you private key, or connect to an instance and get it again... 🤷‍♂️

Do you mind me closing this issue?

Thanks!

@Ninir Ninir added the waiting-response Maintainers are waiting on response from community or contributor. label Aug 21, 2017
@iserko
Copy link
Author

iserko commented Aug 21, 2017

@Ninir, I understand the reason for why it doesn't currently work as advertised.

Four options are possible:

  1. make terraform import accept an attribute for public key ... ex. terraform import aws_key_pair.igor igor_20150712 igor_20150712.pub, which populates the value of the public key in the terraform.tfstate file
  2. mention this problem in the docs https://www.terraform.io/docs/providers/aws/r/key_pair.html ... still says nothing about needing to manually change the terraform.tfstate file and adding public_key yourself
  3. remove the possibility to import aws_key_pair ... rather not do this one
  4. leave it as is, with a mention in the docs that this will result in the key pair being destroyed and recreated

As it stands right now if you want to import it at the moment, manually changing terraform.tfstate is your only way to go, without destroying and recreating the resource.

@recurrence
Copy link

recurrence commented Aug 21, 2017

+1 to 1! I suppose this breaks with the current form of the import statement but taking a secondary argument is a natural progression. That would save the manual state edit while waiting for AWS to return it.

@catsby
Copy link
Contributor

catsby commented Aug 21, 2017

@Ninir I think we may be able to get around this by using a custom import method that simply sets public_key to "", what do think?

@paddycarver paddycarver removed the waiting-response Maintainers are waiting on response from community or contributor. label Nov 21, 2017
@bflad bflad added the service/ec2 Issues and PRs that pertain to the ec2 service. label Jan 28, 2018
@tuwid
Copy link

tuwid commented May 23, 2018

@iserko
My workaround to this was to put the pub key directly in the "public_key" directive as "ssh-rsa..." and it worked as expected. Also be careful when referencing to this object as its not the key.id but the key.name thing you should reference to in your script.

@Ninir
Copy link
Contributor

Ninir commented Jun 6, 2019

Hi folks,

Circling back to that, editing the state is the only viable solution for now. I created a PR to expose that.
Augmenting the import command is not something I am aware of and would require a lot of thoughts to make it right, especially since this is part of the Terraform core.

I hope documenting this edge case is enough. Let me know!

@bflad
Copy link
Contributor

bflad commented Jun 6, 2019

If there is a safe character delimiter we can use, we can optionally allow the import ID to contain both the key name and public key, e.g. with a comma (,) delimiter

$ terraform import aws_key_pair.example 'example,ssh-rsa AAAA...ZZZ== [email protected]'

Then in the import code it can check for the delimiter to perform either a combined import or fallback to the old behavior of just a key name import. 😄

@fdemmer
Copy link

fdemmer commented Sep 25, 2020

Wouldn't the fingerprint be the more correct way to match a remote key with local state?

@raymondberg
Copy link

I'm fairly new to all of this, but I thought I'd leave a helper that I needed when I was building context. I agree some tooling would be great, but I second the comment that updating the docs would be helpful.

What Works for Me ™️

If you encounter this problem and do not want to create a new resource, you'll need to manually (text-editor) change your tfstate file. Open the JSON in your .tfstate and paste the contents public key into the public_key field field for you aws_key_pair.

Once this is done your terraform should apply cleanly.

@ryanrishi
Copy link

@iainelder
Copy link

You can do the replacement programmatically with jq.

jq \
--arg name "bastion_keypair" \
--arg public_key "ssh-rsa AAAAB3NzaC1yc2E..." \
'
(.resources | map(.name == $name and .type == "aws_key_pair") | index(true)) as $index |
.resources[$index].instances[0].attributes.public_key = $public_key
' \
terraform.tfstate

If the output looks good, save a backup of your previous state, save the output to a file, replace the state with the new output, and the apply command should work as expected.

For help understanding the filter, see these links:

@iserko
Copy link
Author

iserko commented Apr 22, 2021

Lots of workarounds described, so that should be enough for now. Closing the issue as it is quite old already.

@iserko iserko closed this as completed Apr 22, 2021
@github-actions
Copy link

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.
If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 23, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Addresses a defect in current functionality. service/ec2 Issues and PRs that pertain to the ec2 service.
Projects
None yet