1
0
Fork 0
mirror of https://github.com/ansible-collections/hetzner.hcloud.git synced 2026-02-04 08:01:49 +00:00

feat: allow recreating ssh key when public key in the API does not match (#634)

##### SUMMARY

- Log a warning when the provided public key does not match one in the
API.
- When the public key does not match the one in the API, allow
recreating the SSH Key in the API using the ``force=true`` argument.


Closes: #578 

##### ISSUE TYPE
- Feature Pull Request

##### COMPONENT NAME
<!--- Write the short name of the module, plugin, task or feature below
-->
`ssh_key`

##### ADDITIONAL INFORMATION
In Hetzner API, we do not have any public_key change endpoint and only
updating names and labels are allowed.
For public_key The only way is removing and re-creating. `force` option
allows users to do re-creation if needed.

---------

Co-authored-by: jo <ljonas@riseup.net>
This commit is contained in:
Amirhossein Shaerpour 2025-06-03 19:13:54 +03:30 committed by GitHub
parent 1ec09d252d
commit 4fc2003f30
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 121 additions and 2 deletions

View file

@ -17,3 +17,15 @@
path: "{{ _tmp_ssh_key_file.path }}"
force: true
register: test_ssh_keypair
- name: Create temporary file for test_ssh_keypair2
ansible.builtin.tempfile:
path: ~/tmp
suffix: "{{ hcloud_ssh_key_name }}"
register: _tmp_ssh_key_file2
- name: Create test_ssh_keypair2
community.crypto.openssh_keypair:
path: "{{ _tmp_ssh_key_file2.path }}"
force: true
register: test_ssh_keypair2

View file

@ -93,7 +93,7 @@
key: value
test: "val123"
register: result
- name: test update ssh key with other labels
- name: test update ssh key with other labels
assert:
that:
- result is changed
@ -136,9 +136,45 @@
- result is failed
- result.failure.code == "uniqueness_error"
- name: test update public key warning
hetzner.hcloud.ssh_key:
name: "{{ hcloud_ssh_key_name }}"
public_key: "{{ test_ssh_keypair2.public_key }}"
register: result
- name: verify update public key warning
assert:
that:
- result is not changed
- result.hcloud_ssh_key.name == hcloud_ssh_key_name
- result.hcloud_ssh_key.public_key == test_ssh_keypair.public_key
- name: test update public key with force
hetzner.hcloud.ssh_key:
name: "{{ hcloud_ssh_key_name }}"
public_key: "{{ test_ssh_keypair2.public_key }}"
force: true
register: result
- name: verify update public key with force
assert:
that:
- result is changed
- result.hcloud_ssh_key.name == hcloud_ssh_key_name
- result.hcloud_ssh_key.public_key == test_ssh_keypair2.public_key
- name: test update public key with force idempotence
hetzner.hcloud.ssh_key:
name: "{{ hcloud_ssh_key_name }}"
public_key: "{{ test_ssh_keypair2.public_key }}"
force: true
register: result
- name: verify update public key with force idempotence
assert:
that:
- result is not changed
- name: test delete ssh key
hetzner.hcloud.ssh_key:
id: "{{ ssh_key.hcloud_ssh_key.id }}"
name: "{{ hcloud_ssh_key_name }}"
state: absent
register: result
- name: verify absent ssh_key

View file

@ -0,0 +1,27 @@
from __future__ import annotations
import pytest
from ansible_collections.hetzner.hcloud.plugins.module_utils.ssh import (
ssh_public_key_md5_fingerprint,
)
@pytest.mark.parametrize(
("public_key", "fingerprint"),
[
(
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILNWUEdTk1oxrjUZ5erbKUmJM3VxQ9DLocgt/HFohCf6 comment",
"ce:cf:37:b9:38:40:ad:80:b2:8b:2c:5c:83:b5:af:0b",
),
(
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILNWUEdTk1oxrjUZ5erbKUmJM3VxQ9DLocgt/HFohCf6", # No comment
"ce:cf:37:b9:38:40:ad:80:b2:8b:2c:5c:83:b5:af:0b",
),
(
"ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBABOUmmgxbhhauMg97GMwHcjWXM35MwFmlSKx7klWpPr3jMbabGQzINFVXexgf6Tru0D5a7NU/Hkx9t2yOtqKHJOIQB5/NKktqYelul4X56WYV/64RSm6xIjcolNao9fUbawnIwh9mvaQQg5v1BiJfPJ6p6LcWPunzfm6DztU1tHwLtjTw== comment", # noqa: E501
"bf:61:7b:7f:ab:c7:af:25:aa:d7:d5:e8:5f:87:5c:66",
),
],
)
def test_ssh_public_key_md5_fingerprint(public_key: str, fingerprint: str):
assert ssh_public_key_md5_fingerprint(public_key) == fingerprint