diff --git a/changelogs/fragments/61658-openssh_keypair-public-key-permissions.yml b/changelogs/fragments/61658-openssh_keypair-public-key-permissions.yml new file mode 100644 index 00000000000..ad4b9dcc030 --- /dev/null +++ b/changelogs/fragments/61658-openssh_keypair-public-key-permissions.yml @@ -0,0 +1,2 @@ +bugfixes: +- "openssh_keypair - public key's file attributes (permissions, owner, group, etc.) are now set to the same values as the private key." diff --git a/docs/docsite/rst/porting_guides/porting_guide_2.9.rst b/docs/docsite/rst/porting_guides/porting_guide_2.9.rst index ffa731434c4..6c5ec0abf61 100644 --- a/docs/docsite/rst/porting_guides/porting_guide_2.9.rst +++ b/docs/docsite/rst/porting_guides/porting_guide_2.9.rst @@ -673,6 +673,7 @@ Noteworthy module changes * The deprecated ``force`` option in ``win_firewall_rule`` has been removed. * :ref:`openssl_certificate `'s ``ownca`` provider creates authority key identifiers if not explicitly disabled with ``ownca_create_authority_key_identifier: no``. This is only the case for the ``cryptography`` backend, which is selected by default if the ``cryptography`` library is available. * :ref:`openssl_certificate `'s ``ownca`` and ``selfsigned`` providers create subject key identifiers if not explicitly disabled with ``ownca_create_subject_key_identifier: never_create`` resp. ``selfsigned_create_subject_key_identifier: never_create``. If a subject key identifier is provided by the CSR, it is taken; if not, it is created from the public key. This is only the case for the ``cryptography`` backend, which is selected by default if the ``cryptography`` library is available. +* :ref:`openssh_keypair ` now applies the same file permissions and ownership to both public and private keys (both get the same ``mode``, ``owner``, ``group``, etc.). If you need to change permissions / ownership on one key, use the :ref:`file ` to modify it after it is created. Plugins diff --git a/lib/ansible/modules/crypto/openssh_keypair.py b/lib/ansible/modules/crypto/openssh_keypair.py index cb5e522060a..63117f91dc7 100644 --- a/lib/ansible/modules/crypto/openssh_keypair.py +++ b/lib/ansible/modules/crypto/openssh_keypair.py @@ -202,7 +202,7 @@ class Keypair(object): self.remove() module.fail_json(msg="%s" % to_native(e)) - elif not self.isPublicKeyValid(module): + elif not self.isPublicKeyValid(module, perms_required=False): pubkey = module.run_command([module.get_bin_path('ssh-keygen', True), '-yf', self.path]) pubkey = pubkey[1].strip('\n') try: @@ -230,6 +230,9 @@ class Keypair(object): file_args = module.load_file_common_arguments(module.params) if module.set_fs_attributes_if_different(file_args, False): self.changed = True + file_args['path'] = file_args['path'] + '.pub' + if module.set_fs_attributes_if_different(file_args, False): + self.changed = True def isPrivateKeyValid(self, module, perms_required=True): @@ -268,7 +271,7 @@ class Keypair(object): return _check_state() and _check_perms(module) and _check_type() and _check_size() - def isPublicKeyValid(self, module): + def isPublicKeyValid(self, module, perms_required=True): def _get_pubkey_content(): if os.path.exists(self.path + ".pub"): @@ -296,6 +299,11 @@ class Keypair(object): return pubkey_parts[2] == self.comment return False + def _check_perms(module): + file_args = module.load_file_common_arguments(module.params) + file_args['path'] = file_args['path'] + '.pub' + return not module.set_fs_attributes_if_different(file_args, False) + pubkey = module.run_command([module.get_bin_path('ssh-keygen', True), '-yf', self.path]) pubkey = pubkey[1].strip('\n') pubkey_parts = _parse_pubkey() @@ -305,7 +313,10 @@ class Keypair(object): if not self.comment: return _pubkey_valid(pubkey) - return _pubkey_valid(pubkey) and _comment_valid() + if not perms_required: + return _pubkey_valid(pubkey) and _comment_valid() + + return _pubkey_valid(pubkey) and _comment_valid() and _check_perms(module) def dump(self): # return result as a dict