-
Notifications
You must be signed in to change notification settings - Fork 2k
Support specifying custom SSH public key. #970
Conversation
This commit updates Streisand to allow enabling/disabling the core services at install time, or by customizing a site specific config file before running Streisand. Ansible's prompt functionality is unfortunately crippled with respect to templating and `when` conditions. This makes it tricky to accomplish the customization we want where you are only prompted for each service if you want to customize the overall installation. To allowing changing services on a per-site basis & remembering the decision the wrapper script now creates a `$HOME/.streisand` directory with a `$HOME/.streisand/site.yml` site specific config file. By default it is populated with the `global_vars/default-site.yml` file from the Streisand repository. The `streisand` wrapper conditionally invokes a separate playbook (`playbooks/customize.yml`) for customization that rewrites the `$HOME/.streisand/site.yml` vars file based on what the user specifies. It's a little bit ugly but It Works(!). Further refinement welcome! This methodology also supports customizing the installed services non-interactively by editing `$HOME/.streisand/site.yml` ahead of running `./streisand` and skipping the customization step. This is useful if (for example) you only ever want to install Wireguard on your Streisand instances. You can create a `$HOME/.streisand/site.yml` that only enables Wireguard and all of your Streisand instances will be provisioned accordingly. The validation role is run after customization to ensure that the choices are valid and don't result in (for e.g.) no services enabled. Presently both Travis and the Vagrant `streisand-host` ignore the `$HOME/.streisand.yml` and use the `global_vars/default-site.yml` vars resulting in a provision with all services enabled.
Prior to this commit Streisand universally assumed the user's SSH public key was `~/.ssh/id_rsa.pub`. This SSH key was then used to provision cloud instances. This commit adds a new `streisand_ssh_key` var to the `global_vars/default-site.yml` file. The site-specific override for these defaults, `~/.streisand/site.yml` is now customized by `playbooks/customize.yml` when the user specifies that they want to use a different SSH pubkey. The user is expected to have the private component loaded into their ssh agent or to customize Ansible to know how to load it. The validation playbook is updated to check that the `streisand_ssh_key` exists. The corresponding shell based checks for the SSH key were removed from the `./streisand` wrapper script since they are now replaced by these Ansible tasks. Similarly the existing server playbook now performs its own quick test of a raw_cmd on the server instead of doing a SSH check in the `./streisand` wrapper. This means things fail a little bit later in the process if you can't actually SSH to the existing server but it isn't *much* later in the process and its nice to rm some shell script code. Three unrelated bugs were fixed with the existing server provisioning. First: There was a typo in the `./streisand` wrapper script's `local_provision` function that was running a non-existent playbook. Second: the genesis role was not being saved as a fact on localhost causing the diagnostics to print "unknown" for the genesis role used. Lastly, because no `gather_facts: yes` for the localhost was run for the existing server provision other diagnostic information was missing. This was also the root cause of Issue StreisandEffect#739. All of the above are now fixed! Yay \o/
This reverts commit 99241d9.
This commit reworks the previous custom SSH key support in order to allow setting the `ansible_ssh_private_key_file` fact. Previously the customization role allowed setting a SSH *public key* that would be used for server provisioning. It was assumed that the user would load this key in their ssh-agent before running Streisand. This commit updates support to instead proactively set the `ansible_ssh_private_key_file` for the Streisand SSH key specified. This ensures Ansible will load & use this private key to access the streisand-host bypassing the need to use a ssh-agent. Doing so required changing the customization to prompt for the *private key* and adjusting other roles accordingly. Work is done to ensure that the existing-server provisioning SSH test still functions the way it did when the `streisand` wrapper script was used to test with a direct `ssh` invocation.
This commit updates the `tests/run.yml` and `tests/vars_ci.yml` to support the custom SSH key work. Primarily this means making sure that the one-off SSH key generated in `/tmp` is properly configured as the Streisand SSH key.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor grammatical nitpick, otherwise I was able to run your branch with a newly generated ssh-key against DO with no issues.
Nice work @cpu!
playbooks/customize.yml
Outdated
@@ -4,6 +4,10 @@ | |||
gather_facts: no | |||
|
|||
vars_prompt: | |||
- name: streisand_ssh_private_key | |||
prompt: "Enter the path to your SSH private key? Press enter for default " |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Enter the path to your SSH private key, or press enter for default" reads a bit better in my opinion. Either way the question mark can be dropped.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! fixed in ef529d1
rescue: | ||
- fail: | ||
msg: "Unable to SSH to existing streisand-host.\nEnsure private key corresponding to \"{{ streisand_ssh_key }}\" is loaded in your SSH key agent.\nTry using `ssh-keygen -i {{ streisand_ssh_key }} to generate your key if it does not exist\n" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good hint 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
\o/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would this be simpler if we could guarantee Ansible runs under an ssh-agent, either an existing one or a freshly launched one? I ask because my ssh-agent talks to my Yubikey, so in some sense I don't have an id_rsa
, only an id_rsa.pub
.
We do need something id_rsa.pub
-like, because we need to push it into authorized_keys
. If we were super-crazy, we could fish the pubkeys out of the agent with ssh-add -L
: have the user select from the human-readable names in the last column, probably.
Backing up a little, this PR resolves those bug reports and it answers immediate needs, so I'm going to hit the Approve button, since what PR sets out to do, it does nicely.
(In the Docker-hacks version of ./streisand
I force the user to authenticate with ssh-add
. Here
It doesn't sound simpler to me :-) I'll give it some thought but I likely won't work on it myself if you're interested in trying as a follow-up. If so creating a second issue with some prelim details and assigning it to yourself would be great. Thanks! |
Prior to this PR Streisand universally assumed the user's SSH private key was
~/.ssh/id_rsa
. The public component was then used to provision cloud instances.This PR adds a new
streisand_ssh_private_key
var to theglobal_vars/default-site.yml
file. The site-specific override for these defaults,~/.streisand/site.yml
is now customized byplaybooks/customize.yml
when the user specifies that they want to use a different SSH key. The public component is expected to exist at the same file path with a.pub
suffix to keep things simple.This PR proactively sets the
ansible_ssh_private_key_file
for the Streisand SSH key specified. This ensures Ansible will load & use this private key to access the streisand-host bypassing the need to use a ssh-agent (though it will play nicely if you do).The validation playbook is updated to check that the
streisand_ssh_private_key
exists. The corresponding shell based checks for the SSH key were removed from the./streisand
wrapper script since they are now replaced by these Ansible tasks. Similarly the existing server playbooknow performs its own quick test of a raw_cmd on the server instead of doing a SSH check in the
./streisand
wrapper. This means things fail a little bit later in the process if you can't actually SSH to theexisting server but it isn't much later in the process and its nice to
rm
some shell script code.Two unrelated bugs were fixed with the existing server provisioning: the genesis role was not being saved as a fact on localhost causing the diagnostics to print "unknown" for the genesis role used. Secondly, because no
gather_facts: yes
for the localhost was run for the existing server provision other diagnostic information was missing. This was also the root cause of Issue #739.Resolves #739, #300
I have tested this PR with a few providers (Linode, DigitalOcean, Existing Server, Localhost) using my own SSH key loaded in an ssh-agent ahead of time as well as with a brand new ed25519 keypair that used a passphrase. Both cases worked as expected.