Manage bastion SSH known_hosts file

This attempts to manage the SSH host keys of all the hosts in the
inventory. The idea here is each host in the inventory will add a
ansible_ssh_host_key_ecdsa_public variable, then when we first run our
bastion playbook we'll properly populate the local known_hosts file each
time.

Change-Id: I26e328192a7127086e514dc62a27cb946a77440b
Depends-On: https://review.openstack.org/643408
Signed-off-by: Paul Belanger <pabelanger@redhat.com>
This commit is contained in:
Paul Belanger 2019-03-13 21:09:24 -04:00
parent 6f7db58426
commit 1d490a3729
4 changed files with 51 additions and 2 deletions

View File

@ -69,6 +69,10 @@ def bootstrap_server(server, key, name, group, keep, timeout):
ansible_user = None
print("--- Running initial configuration on host %s ---" % ip)
host_key = utils.nodescan(ip)
if not host_key:
raise Exception("Unable to find ssh-ecdsa SSH host key")
for username in ['ubuntu', 'centos']:
ssh_client = utils.ssh_connect(
ip, username, ssh_kwargs, timeout=timeout)
@ -87,9 +91,10 @@ def bootstrap_server(server, key, name, group, keep, timeout):
with open(runner.hosts, 'w') as inventory_file:
inventory_file.write(
"[{group}]\n{host} ansible_host={ip} "
"ansible_user={user}".format(
"ansible_user={user} "
"ansible_ssh_host_key_ed25519_public={host_key}".format(
group=group, host=name, ip=server.interface_ip,
user=ansible_user))
user=ansible_user, host_key=host_key))
project_dir = os.path.join(
SCRIPT_DIR, '..', 'playbooks', 'bootstrap-ansible')

View File

@ -15,6 +15,7 @@
# limitations under the License.
import socket
import subprocess
import time
import paramiko
@ -32,6 +33,30 @@ def iterate_timeout(max_seconds, purpose):
raise Exception("Timeout waiting for %s" % purpose)
def nodescan(ip, port=22, timeout=60):
"""Scan the IP address for public SSH keys.
Returns SSH host key
"""
key = None
output = None
for count in iterate_timeout(
timeout, "connection to %s on port %s" % (ip, port)):
try:
output = subprocess.check_output(
['ssh-keyscan', '-t', 'ed25519', '-p', str(port), str(ip)])
if output:
break
except Exception as e:
print("ssh-keyscan failure: %s", e)
key = output.split()[2].decode('utf8')
return key
def ssh_connect(ip, username, connect_kwargs={}, timeout=60):
# HPcloud may return errno 111 for about 30 seconds after adding the IP
for count in iterate_timeout(timeout, "ssh access"):

View File

@ -12,6 +12,15 @@
# License for the specific language governing permissions and limitations
# under the License.
---
- name: Configure bastion SSH known_hosts
hosts: bastion:!disabled
gather_facts: false
tasks:
- name: Ensure SSH host keys are known
template:
dest: ~/.ssh/known_hosts
src: bastion/root/.ssh/known_hosts.j2
- name: Bootstrap all hosts
hosts: all:!disabled
tasks:

View File

@ -0,0 +1,10 @@
# This file is generated by Ansible
# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
#
{% for host in groups['all'] %}
{% if hostvars[host].ansible_host is defined %}
{% if hostvars[host].ansible_ssh_host_key_ed25519_public is defined %}
{{ hostvars[host].ansible_host }} ssh-ed25519 {{ hostvars[host].ansible_ssh_host_key_ed25519_public }}
{% endif %}
{% endif %}
{% endfor %}