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

openssh_keypair handles encrypted key files poorly #63910

Closed
thomwiggers opened this issue Oct 24, 2019 · 10 comments · Fixed by #64436
Closed

openssh_keypair handles encrypted key files poorly #63910

thomwiggers opened this issue Oct 24, 2019 · 10 comments · Fixed by #64436
Labels
affects_2.8 This issue/PR affects Ansible v2.8 bug This issue/PR relates to a bug. crypto Crypto community (ACME, openssl, letsencrypt) has_pr This issue has an associated PR. module This issue/PR relates to a module. python3 support:community This issue/PR relates to code supported by the Ansible community.

Comments

@thomwiggers
Copy link
Contributor

thomwiggers commented Oct 24, 2019

SUMMARY

openssh_keypair handles encrypted key files poorly.

ISSUE TYPE
  • Bug Report
COMPONENT NAME

openssh_keypair

ANSIBLE VERSION
ansible 2.8.5
  config file = /home/thom/git/dotfiles-ansible/ansible.cfg
  configured module search path = ['/home/thom/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 3.7.4 (default, Oct  4 2019, 06:57:26) [GCC 9.2.0]
CONFIGURATION
ANSIBLE_NOCOWS(/home/thom/git/dotfiles-ansible/ansible.cfg) = True
DEFAULT_HOST_LIST(/home/thom/git/dotfiles-ansible/ansible.cfg) = ['/home/thom/git/dotfiles-ansible/hosts']
DEFAULT_MANAGED_STR(/home/thom/git/dotfiles-ansible/ansible.cfg) = This file is managed by Ansible.%n
template: {file}
date: %Y-%m-%d %H:%M:%S
user: {uid}
host: {host}
OS / ENVIRONMENT

Arch Linux

OpenSSH_8.1p1, OpenSSL 1.1.1d 10 Sep 2019

STEPS TO REPRODUCE
  - name: Obtain keyfile from this machine                                          
    openssh_keypair:                                                                
      path: "/tmp/sshkey"
      type: ed25519

I'm using ed25519 because it's independent of size; not sure if it also happens with eg. RSA.

  1. Generate /tmp/sshkey using ssh-keygen -t ed25519 -f /tmp/sshkey -N password
  2. Run the above playbook, observe it marks it as changed.
  3. Observe /tmp/sshkey.pub is now empty.
  4. Run it again, it's changed again
  5. It has now replaced the SSH key and the public key is now correct.
EXPECTED RESULTS
  1. Either give me an error about encrypted .ssh files already existing or properly replace it.
@ansibot
Copy link
Contributor

ansibot commented Oct 24, 2019

Files identified in the description:

If these files are inaccurate, please update the component name section of the description or use the !component bot command.

click here for bot help

@ansibot
Copy link
Contributor

ansibot commented Oct 24, 2019

@ansibot ansibot added affects_2.8 This issue/PR affects Ansible v2.8 bug This issue/PR relates to a bug. crypto Crypto community (ACME, openssl, letsencrypt) module This issue/PR relates to a module. needs_triage Needs a first human triage before being processed. python3 support:community This issue/PR relates to code supported by the Ansible community. labels Oct 24, 2019
@felixfontein
Copy link
Contributor

Interestingly, for me both tasks are unchanged on the second run. My OpenSSH version: OpenSSH_8.1p1, OpenSSL 1.1.1d 10 Sep 2019 I guess we should add tests for this to the integration tests, then we'll probably notice for which versions of works and for which it doesn't. :)

@ansibot ansibot removed the needs_triage Needs a first human triage before being processed. label Oct 24, 2019
@thomwiggers
Copy link
Contributor Author

thomwiggers commented Oct 25, 2019

hrm, something funky is going on. If I run my example it indeed works as expected. I'm on the same OpenSSH version.

However, if I target my existing ~/.ssh/id_ed25519{,.pub} files, it first blanks out the .ssh/id_ed25519.pub file and somehow breaks the private key file! (ssh-keygen -lf ~/.ssh/id_ed25519 says is not a key file), although diff can't find a difference??? This is all very weird.

@thomwiggers
Copy link
Contributor Author

...... Wait, I think the difference is that my key is password protected. I think it probably handles that poorly.

@thomwiggers
Copy link
Contributor Author

Ahh, and is not a valid key file happens if the .pub file is broken, caused by the former.

@thomwiggers
Copy link
Contributor Author

I've updated my testcase above, I'll also change the title.

@thomwiggers thomwiggers changed the title openssh_keypair always changes ed25519 key openssh_keypair handles encrypted key files poorly Oct 25, 2019
@felixfontein
Copy link
Contributor

Here's a pure-ansible reproducer:

---
- hosts: localhost
  tasks:
    - file:
        path: /tmp/sshkey
        state: absent
    - file:
        path: /tmp/sshkey.pub
        state: absent
    - command: ssh-keygen -t ed25519 -f /tmp/sshkey -N password
    - stat:
        path: "{{ item }}"
      loop:
        - /tmp/sshkey
        - /tmp/sshkey.pub
      register: out
    - debug:
        msg: "Key:{{ out.results[0].stat.size }}/{{ out.results[0].stat.mtime }} Pub:{{ out.results[1].stat.size }}/{{ out.results[1].stat.mtime }}"
    - openssh_keypair:                                                                
        path: "/tmp/sshkey"
        type: ed25519
    - stat:
        path: "{{ item }}"
      loop:
        - /tmp/sshkey
        - /tmp/sshkey.pub
      register: out
    - debug:
        msg: "Key:{{ out.results[0].stat.size }}/{{ out.results[0].stat.mtime }} Pub:{{ out.results[1].stat.size }}/{{ out.results[1].stat.mtime }}"
    - openssh_keypair:                                                                
        path: "/tmp/sshkey"
        type: ed25519
    - stat:
        path: "{{ item }}"
      loop:
        - /tmp/sshkey
        - /tmp/sshkey.pub
      register: out
    - debug:
        msg: "Key:{{ out.results[0].stat.size }}/{{ out.results[0].stat.mtime }} Pub:{{ out.results[1].stat.size }}/{{ out.results[1].stat.mtime }}"

In the first openssh_keypair call, https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/crypto/openssh_keypair.py#L307 is executed and returns '' as stdout. Since that's different from the current public key, it will be overwritten. In the second openssh_keypair call, https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/crypto/openssh_keypair.py#L244 will fail since it uses the .pub file. So it will regenerate the key itself.

I guess we need to add a "can we actually read the key itself" test and a "is they key maybe password protected" test.

Anyone wants to (try to) implement that?

@felixfontein
Copy link
Contributor

Already checking return values for the calls above might already improve the situation a lot.

@MaxBab
Copy link
Contributor

MaxBab commented Nov 5, 2019

Hi @thomwiggers @felixfontein

The fix will check every private key for the password protected state.
If the key is password protected, the task will fail with the message.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
affects_2.8 This issue/PR affects Ansible v2.8 bug This issue/PR relates to a bug. crypto Crypto community (ACME, openssl, letsencrypt) has_pr This issue has an associated PR. module This issue/PR relates to a module. python3 support:community This issue/PR relates to code supported by the Ansible community.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants