gruntwork-io / terratest

Terratest is a Go library that makes it easier to write automated tests for your infrastructure code.
https://terratest.gruntwork.io/
Apache License 2.0
7.52k stars 1.33k forks source link

gcp compute AddSshKey limitation #677

Open alexandruy2k opened 4 years ago

alexandruy2k commented 4 years ago

Hi,

I'm trying to use terratest to create a gcp machine and ssh into it to do some tests.

The problem is that AddSshKey fails with the following error:

Metadata has duplicate keys: ssh-keys, invalid

I've traced it down and the reason for that is that for the instance in terraform I have already set a bunch of ssh keys in the metadata for user access using:

  metadata = {
    ssh-keys = var.public_keys
  }

AddSshKey just appends to the metadata by adding another ssh-keys key instead of appending to the existing key.

So I'm wondering what's the recommended way for terratest to ssh in given that I already have some ssh-keys already populated. I'm using var.public_keys as the mechanism to give users access to the real instance.

Thank you very much,

Alex

robmorgan commented 4 years ago

Hi @alexandruy2k,

Thanks for your issue. We've intentionally kept this fairly simple using documented metadata approach for instance-level SSH keys so this is not something we are planning to change for the moment. The same logic also applies to other areas where we are using instance metadata to control startup and shutdown scripts. It would get very sticky if we allowed the user to also BYO their own scripts and we had to append them somehow if they called our methods, so by principle we try to avoid competing for the same variable.

I would however suggest either one of the following approaches:

  1. Avoid using AddSshKey and instead ensure Terratest/Go has access to the SSH keys you are setting on the instance. This way Terratest should be able to successfully authenticate and access the instance. You can find an example here, just try to omit the method.
  2. Remove your public keys from the instance: Is there any specific reason you want to associate SSH keys with the instance? Are they added as part of a module intended for production usage? You could allow Terratest to generate the SSH key pair and then use this if you ever need to manually debug your tests.
  3. Investigate if it makes sense to include support for OS Login in Terratest. I don't have the time to investigate this currently and work on a PoC, but I'd be more than happy to review anything you might contribute.

I hope that helps.

Regards,

Rob

alexandruy2k commented 4 years ago

@robmorgan thanks very much. I went at least initially with option 1. I have a TF_VAR that I use to inject the public ssh keys for all the users allowed to ssh in production. So for my terratest I just generate a new keypair and append it onto my TF_VAR and that when when I deploy the machine it has the user ssh keys and an extra one apended for terratest

  1. I have the following in my main terraform file for the vm instance metadata = { ssh-keys = var.public_keys }

Which means that terraform will always try to inject "ssh-keys" into the instance. If I was to remove it from terraform I'm not sure how I would add it back into the production instance using terraform. I don't want to resort to using the google sdk to add ssh keys after the deployment.

  1. We currently don't have OS Login enabled in the project, but yes definitelly once we enable that, using terratest with OS Login will simplify things a lot.

you mentioned that terratest adds startup scripts in metadata as well. Where is that? Because we also have a startup script in the machine added to the metadata and I've seen some rare occurrences where terratest would complain about duplicate metadata. If you can point me to where terratest injects startup metadata it would help me understand the errors in case they become a more regular occurence

robmorgan commented 4 years ago

Hi @alexandruy2k, understood. Yes if I were you I invest time into exploring OS Login as you get the benefit of managing users using IAM permissions. This follows a similar approach to how we manage SSH users for AWS EC2 instances in our commercial Gruntwork products.

you mentioned that terratest adds startup scripts in metadata as well. Where is that?

There is no explicit helper method in the Terratest library that currently does this, nor do I have any open-source examples. At the moment we only do this is our private repositories. I can however point you to an open-source Terraform example so you can see what the code looks like. As I mentioned earlier, you would need to omit this if you are injecting metadata using Terratest.