saltstack / salt

Software to automate the management and configuration of any infrastructure or application at scale. Install Salt from the Salt package repositories here:
https://docs.saltproject.io/salt/install-guide/en/latest/
Apache License 2.0
14.19k stars 5.48k forks source link

[BUG] ssh_known_hosts.present fails when updating due to ssh.set_known_host not returning a fingerprint #63602

Closed TimidRobot closed 1 year ago

TimidRobot commented 1 year ago

Description Here is what I observed:

  1. /root/.ssh/known_hosts already contains an entry for the host
  2. ssh_known_hosts.present is appending a new line to /root/.ssh/known_hosts (not replacing, despite 'status': 'updated')
  3. ssh.set_known_host returns a result without a fingerprint:
     {
        'status': 'updated',
        'old': [{
            'hostname': '|1|5jPU4BdHiB4E2uxpJYGgXsmeGvA=|Xp0rhxgiWLXb/rQQdHw4kPbnHjw=',
            'key': 'AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIJV2aUsnc/U24icd+s8SpFQWmocQ6tb7aHLG0Vr817ZuzWOjFuvuv7ofckpnliQOK4wHeczzroN0ePw5pBEgLE=',
            'enc': 'ecdsa-sha2-nistp256',
            'fingerprint': '0d:a6:7f:b3:52:2a:17:19:a0:28:2e:c4:43:6a:a1:98:67:c0:d1:81:92:ca:9e:c9:24:f0:07:4c:c0:ed:4d:f2'
        }],
        'new': [{
            'hostname': '10.22.10.16',
            'enc': None,
            'key': 'AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJekNzEqtK7NHvQ1pQup0f5UK7JdOXCdpKeIYv8BigTOtGdph1kD/AaQIM8YLzGE4Os+5R3aShkJ6CKnggnITHA='
        }]
    }
  4. ssh_known_hosts.present successfully adds (appends) the new entry to known_hosts, but the state fails with an exception due to Line 190:
    An exception occurred in this state: Traceback (most recent call last):
                File "/usr/lib/python3/dist-packages/salt/state.py", line 2179, in call
                  ret = self.states[cdata["full"]](
                File "/usr/lib/python3/dist-packages/salt/loader/lazy.py", line 149, in __call__
                  return self.loader.run(run_func, *args, **kwargs)
                File "/usr/lib/python3/dist-packages/salt/loader/lazy.py", line 1201, in run
                  return self._last_context.run(self._run_as, _func_or_method, *args, **kwargs)
                File "/usr/lib/python3/dist-packages/salt/loader/lazy.py", line 1216, in _run_as
                  return _func_or_method(*args, **kwargs)
                File "/usr/lib/python3/dist-packages/salt/loader/lazy.py", line 1249, in wrapper
                  return f(*args, **kwargs)
                File "/usr/lib/python3/dist-packages/salt/states/ssh_known_hosts.py", line 190, in present
                  fingerprint = result["new"][0]["fingerprint"]
              KeyError: 'fingerprint'
  5. Removing the old entry ('hostname': '|1|5jPU4BdHiB4E2uxpJYGgXsmeGvA=|Xp0rhxgiWLXb/rQQdHw4kPbnHjw=') causes the process to succeed

Setup

Please be as specific as possible and give set-up details.

Steps to Reproduce the behavior (Include debug logs if possible and relevant)

Expected behavior

Screenshots If applicable, add screenshots to help explain your problem.

Versions Report

salt --versions-report (Provided by running salt --versions-report. Please also mention any differences in master/minion versions.) ```yaml Salt Version: Salt: 3004.2 Dependency Versions: cffi: Not Installed cherrypy: Not Installed dateutil: 2.8.1 docker-py: Not Installed gitdb: 4.0.5 gitpython: 3.1.14 Jinja2: 2.11.3 libgit2: Not Installed M2Crypto: Not Installed Mako: Not Installed msgpack: 1.0.0 msgpack-pure: Not Installed mysql-python: Not Installed pycparser: Not Installed pycrypto: Not Installed pycryptodome: 3.9.7 pygit2: Not Installed Python: 3.9.2 (default, Feb 28 2021, 17:03:44) python-gnupg: Not Installed PyYAML: 5.3.1 PyZMQ: 20.0.0 smmap: 4.0.0 timelib: Not Installed Tornado: 4.5.3 ZMQ: 4.3.4 System Versions: dist: debian 11 bullseye locale: utf-8 machine: x86_64 release: 5.10.0-20-amd64 system: Linux version: Debian GNU/Linux 11 bullseye ```

Additional context Add any other context about the problem here.

TimidRobot commented 1 year ago

I also encountered this running a highstate (not doing orchestration/provisioning) with version 3005.1:

salt-prime__core__us-east-2:
----------
          ID: salt.prime add GitHub ssh known host entry
    Function: ssh_known_hosts.present
      Result: False
     Comment: An exception occurred in this state: Traceback (most recent call last):
                File "/usr/lib/python3/dist-packages/salt/state.py", line 2276, in call
                  ret = self.states[cdata["full"]](
                File "/usr/lib/python3/dist-packages/salt/loader/lazy.py", line 149, in __call__
                  return self.loader.run(run_func, *args, **kwargs)
                File "/usr/lib/python3/dist-packages/salt/loader/lazy.py", line 1228, in run
                  return self._last_context.run(self._run_as, _func_or_method, *args, **kwargs)
                File "/usr/lib/python3/dist-packages/salt/loader/lazy.py", line 1243, in _run_as
                  return _func_or_method(*args, **kwargs)
                File "/usr/lib/python3/dist-packages/salt/loader/lazy.py", line 1276, in wrapper
                  return f(*args, **kwargs)
                File "/usr/lib/python3/dist-packages/salt/states/ssh_known_hosts.py", line 190, in present
                  fingerprint = result["new"][0]["fingerprint"]
              KeyError: 'fingerprint'
     Started: 16:15:14.009825
    Duration: 371.57 ms
     Changes:   

Summary for salt-prime__core__us-east-2
--------------
Succeeded: 115
Failed:      1
--------------
Total states run:     116
Total run time:    19.567 s

invocation is pretty standard: https://github.com/creativecommons/sre-salt-prime/blob/0efe0d6d695c13b5d28e628522cc42ee595f78a7/states/salt/prime.sls#L28-L31

{{ sls }} add GitHub ssh known host entry:
  ssh_known_hosts.present:
    - name: github.com
    - user: root

Versions Report

salt --versions-report (Provided by running salt --versions-report. Please also mention any differences in master/minion versions.) ```yaml Salt Version: Salt: 3005.1 Dependency Versions: cffi: Not Installed cherrypy: Not Installed dateutil: 2.8.1 docker-py: Not Installed gitdb: 4.0.5 gitpython: 3.1.14 Jinja2: 2.11.3 libgit2: Not Installed M2Crypto: Not Installed Mako: Not Installed msgpack: 1.0.0 msgpack-pure: Not Installed mysql-python: Not Installed pycparser: Not Installed pycrypto: Not Installed pycryptodome: 3.9.7 pygit2: Not Installed Python: 3.9.2 (default, Feb 28 2021, 17:03:44) python-gnupg: Not Installed PyYAML: 5.3.1 PyZMQ: 20.0.0 smmap: 4.0.0 timelib: Not Installed Tornado: 4.5.3 ZMQ: 4.3.4 System Versions: dist: debian 11 bullseye locale: utf-8 machine: x86_64 release: 5.10.0-20-amd64 system: Linux version: Debian GNU/Linux 11 bullseye ```
dmurphy18 commented 1 year ago

@TimidRobot I am a little confused as to the issue here, since you are referring to present which if the host already exists, should return a message alone the lines of

root@tdeb11:/usr/lib/python3/dist-packages# python3 -m pudb.run /usr/bin/salt-call --local state.apply test
local:
----------
          ID: check_ssh_present
    Function: ssh_known_hosts.present
        Name: 192.168.0.109
      Result: True
     Comment: 192.168.0.109 already exists in .ssh/known_hosts
     Started: 16:05:19.930782
    Duration: 397774.824 ms
     Changes:   

Summary for local
------------
Succeeded: 1
Failed:    0
------------
Total states run:     1
Total run time: 397.775 s
root@tdeb11:/usr/lib/python3/dist-packages# 

for state file test.sls

root@tdeb11:/usr/lib/python3/dist-packages# cat /srv/salt/test.sls 
check_ssh_present:
  ssh_known_hosts:
    - name: 192.168.0.109
    - present
    - user: root

If the host is already present in known_hosts file, then it should return the already exists and not the fingerprint, and should not drop through to the lines checking fingerprint. That is lines 177-178 in https://github.com/saltstack/salt/blob/master/salt/states/ssh_known_hosts.py#L165-L198

Can you provide a better example which reproduces the issue you are experiencing, since present appears to be correctly detecting an existing host and returning the appropriate status.

Tested with Salt 3006.2 on Ubuntu 20.04, and Salt 3005.2 on Debian 11.

Used cut down example from https://docs.saltproject.io/en/latest/ref/states/all/salt.states.ssh_known_hosts.html#salt.states.ssh_known_hosts.present

Including a fingerprint resulted in the salt already exists message

root@tdeb11:/srv/salt# python3 -m pudb.run /usr/bin/salt-call --local state.apply test2
local:
----------
          ID: check_ssh_present
    Function: ssh_known_hosts.present
        Name: 192.168.0.109
      Result: True
     Comment: 192.168.0.109 already exists in .ssh/known_hosts
     Started: 16:27:04.222211
    Duration: 17506.031 ms
     Changes:   

Summary for local
------------
Succeeded: 1
Failed:    0
------------
Total states run:     1
Total run time:  17.506 s
root@tdeb11:/srv/salt# cat test2.sls 
check_ssh_present:
  ssh_known_hosts:
    - name: 192.168.0.109
    - present
    - user: root
    - fingerprint: 9c:eb:3b:88:b4:d7:24:76:b7:86:a5:c0:34:11:e4:b4:23:66:ef:08:f6:ce:c6:18:79:51:24:91:9e:6f:55:68
root@tdeb11:/srv/salt# 
dmurphy18 commented 1 year ago

@TimidRobot Perhaps there is somewhere else in your code which is trying to add a host to the known_hosts file and that code may be causing the issue you are encountering. I would expect to drop through to the fingerprint key if there was no host in known_hosts file, but you state that it works when the host is removed from known_hosts file.

dmurphy18 commented 1 year ago

@TimidRobot If there is no response to the issue not being reproducible or other information on how to reproduce the issue, this issue will be closed due to unresponsiveness within a few days

dmurphy18 commented 1 year ago

Closing due to unresponsive