mirror of
https://github.com/ansible-collections/ansible.posix.git
synced 2026-01-13 08:05:19 +01:00
Compare commits
7 commits
793002b98c
...
cf6ec52c85
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cf6ec52c85 | ||
|
|
0821768bcb | ||
|
|
5f3f8514eb | ||
|
|
7e1b76c46e | ||
|
|
505a4aaa09 | ||
|
|
d70d2aaaa7 | ||
|
|
806ff5c1a3 |
6 changed files with 91 additions and 9 deletions
3
changelogs/fragments/568_update_authorized_key.yml
Normal file
3
changelogs/fragments/568_update_authorized_key.yml
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
---
|
||||||
|
minor_changes:
|
||||||
|
- authorized_keys - allow using absolute path to a file as a SSH key(s) source (https://github.com/ansible-collections/ansible.posix/pull/568)
|
||||||
|
|
@ -24,6 +24,7 @@ options:
|
||||||
key:
|
key:
|
||||||
description:
|
description:
|
||||||
- The SSH public key(s), as a string or (since Ansible 1.9) url (https://github.com/username.keys).
|
- The SSH public key(s), as a string or (since Ansible 1.9) url (https://github.com/username.keys).
|
||||||
|
- You can also use V(file://) prefix to search remote for a file with SSH key(s).
|
||||||
type: str
|
type: str
|
||||||
required: true
|
required: true
|
||||||
path:
|
path:
|
||||||
|
|
@ -96,6 +97,12 @@ EXAMPLES = r'''
|
||||||
state: present
|
state: present
|
||||||
key: https://github.com/charlie.keys
|
key: https://github.com/charlie.keys
|
||||||
|
|
||||||
|
- name: Set authorized keys taken from path on controller node
|
||||||
|
ansible.posix.authorized_key:
|
||||||
|
user: charlie
|
||||||
|
state: present
|
||||||
|
key: file:///home/charlie/.ssh/id_rsa.pub
|
||||||
|
|
||||||
- name: Set authorized keys taken from url using lookup
|
- name: Set authorized keys taken from url using lookup
|
||||||
ansible.posix.authorized_key:
|
ansible.posix.authorized_key:
|
||||||
user: charlie
|
user: charlie
|
||||||
|
|
@ -223,6 +230,7 @@ from operator import itemgetter
|
||||||
from ansible.module_utils._text import to_native
|
from ansible.module_utils._text import to_native
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
from ansible.module_utils.urls import fetch_url
|
from ansible.module_utils.urls import fetch_url
|
||||||
|
from ansible.module_utils.six.moves.urllib.parse import urlparse
|
||||||
|
|
||||||
|
|
||||||
class keydict(dict):
|
class keydict(dict):
|
||||||
|
|
@ -556,7 +564,7 @@ def enforce_state(module, params):
|
||||||
follow = params.get('follow', False)
|
follow = params.get('follow', False)
|
||||||
error_msg = "Error getting key from: %s"
|
error_msg = "Error getting key from: %s"
|
||||||
|
|
||||||
# if the key is a url, request it and use it as key source
|
# if the key is a url or file, request it and use it as key source
|
||||||
if key.startswith("http"):
|
if key.startswith("http"):
|
||||||
try:
|
try:
|
||||||
resp, info = fetch_url(module, key)
|
resp, info = fetch_url(module, key)
|
||||||
|
|
@ -570,6 +578,19 @@ def enforce_state(module, params):
|
||||||
# resp.read gives bytes on python3, convert to native string type
|
# resp.read gives bytes on python3, convert to native string type
|
||||||
key = to_native(key, errors='surrogate_or_strict')
|
key = to_native(key, errors='surrogate_or_strict')
|
||||||
|
|
||||||
|
if key.startswith("file"):
|
||||||
|
# if the key is an absolute path, check for existense and use it as a key source
|
||||||
|
key_path = urlparse(key).path
|
||||||
|
if not os.path.exists(key_path):
|
||||||
|
module.fail_json(msg="Path to a key file not found: %s" % key_path)
|
||||||
|
if not os.path.isfile(key_path):
|
||||||
|
module.fail_json(msg="Path to a key is a directory and must be a file: %s" % key_path)
|
||||||
|
try:
|
||||||
|
with open(key_path, 'r') as source_fh:
|
||||||
|
key = source_fh.read()
|
||||||
|
except OSError as e:
|
||||||
|
module.fail_json(msg="Failed to read key file %s : %s" % (key_path, to_native(e)))
|
||||||
|
|
||||||
# extract individual keys into an array, skipping blank lines and comments
|
# extract individual keys into an array, skipping blank lines and comments
|
||||||
new_keys = [s for s in key.splitlines() if s and not s.startswith('#')]
|
new_keys = [s for s in key.splitlines() if s and not s.startswith('#')]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,7 @@ import os
|
||||||
import platform
|
import platform
|
||||||
import re
|
import re
|
||||||
import tempfile
|
import tempfile
|
||||||
|
import glob
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
from ansible.module_utils.six import string_types
|
from ansible.module_utils.six import string_types
|
||||||
|
|
@ -114,12 +115,24 @@ class SysctlModule(object):
|
||||||
# success or failure.
|
# success or failure.
|
||||||
LANG_ENV = {'LANG': 'C', 'LC_ALL': 'C', 'LC_MESSAGES': 'C'}
|
LANG_ENV = {'LANG': 'C', 'LC_ALL': 'C', 'LC_MESSAGES': 'C'}
|
||||||
|
|
||||||
|
# We define a variable to keep all the directories to be read, equivalent to
|
||||||
|
# (/sbin/sysctl --system) option
|
||||||
|
SYSCTL_DIRS = [
|
||||||
|
'/etc/sysctl.d/*.conf',
|
||||||
|
'/run/sysctl.d/*.conf',
|
||||||
|
'/usr/local/lib/sysctl.d/*.conf',
|
||||||
|
'/usr/lib/sysctl.d/*.conf',
|
||||||
|
'/lib/sysctl.d/*.conf',
|
||||||
|
'/etc/sysctl.conf'
|
||||||
|
]
|
||||||
|
|
||||||
def __init__(self, module):
|
def __init__(self, module):
|
||||||
self.module = module
|
self.module = module
|
||||||
self.args = self.module.params
|
self.args = self.module.params
|
||||||
|
|
||||||
self.sysctl_cmd = self.module.get_bin_path('sysctl', required=True)
|
self.sysctl_cmd = self.module.get_bin_path('sysctl', required=True)
|
||||||
self.sysctl_file = self.args['sysctl_file']
|
self.sysctl_file = self.args['sysctl_file']
|
||||||
|
self.system_Wide = self.args['system_Wide']
|
||||||
|
|
||||||
self.proc_value = None # current token value in proc fs
|
self.proc_value = None # current token value in proc fs
|
||||||
self.file_value = None # current token value in file
|
self.file_value = None # current token value in file
|
||||||
|
|
@ -299,15 +312,22 @@ class SysctlModule(object):
|
||||||
# https://github.com/ansible/ansible/issues/58158
|
# https://github.com/ansible/ansible/issues/58158
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
# system supports reloading via the -p flag to sysctl, so we'll use that
|
if self.system_Wide:
|
||||||
sysctl_args = [self.sysctl_cmd, '-p', self.sysctl_file]
|
for sysctl_file in self.SYSCTL_DIRS:
|
||||||
if self.args['ignoreerrors']:
|
for conf_file in glob.glob(sysctl_file):
|
||||||
sysctl_args.insert(1, '-e')
|
rc, out, err = self.module.run_command([self.sysctl_cmd, '-p', conf_file], environ_update=self.LANG_ENV)
|
||||||
|
if rc != 0 or self._stderr_failed(err):
|
||||||
|
self.module.fail_json(msg="Failed to reload sysctl: %s" % to_native(out) + to_native(err))
|
||||||
|
else:
|
||||||
|
# system supports reloading via the -p flag to sysctl, so we'll use that
|
||||||
|
sysctl_args = [self.sysctl_cmd, '-p', self.sysctl_file]
|
||||||
|
if self.args['ignoreerrors']:
|
||||||
|
sysctl_args.insert(1, '-e')
|
||||||
|
|
||||||
rc, out, err = self.module.run_command(sysctl_args, environ_update=self.LANG_ENV)
|
rc, out, err = self.module.run_command(sysctl_args, environ_update=self.LANG_ENV)
|
||||||
|
|
||||||
if rc != 0 or self._stderr_failed(err):
|
if rc != 0 or self._stderr_failed(err):
|
||||||
self.module.fail_json(msg="Failed to reload sysctl: %s" % to_native(out) + to_native(err))
|
self.module.fail_json(msg="Failed to reload sysctl: %s" % to_native(out) + to_native(err))
|
||||||
|
|
||||||
# ==============================================================
|
# ==============================================================
|
||||||
# SYSCTL FILE MANAGEMENT
|
# SYSCTL FILE MANAGEMENT
|
||||||
|
|
@ -394,7 +414,8 @@ def main():
|
||||||
reload=dict(default=True, type='bool'),
|
reload=dict(default=True, type='bool'),
|
||||||
sysctl_set=dict(default=False, type='bool'),
|
sysctl_set=dict(default=False, type='bool'),
|
||||||
ignoreerrors=dict(default=False, type='bool'),
|
ignoreerrors=dict(default=False, type='bool'),
|
||||||
sysctl_file=dict(default='/etc/sysctl.conf', type='path')
|
sysctl_file=dict(default='/etc/sysctl.conf', type='path'),
|
||||||
|
system_wide=dict(default=False, type='bool'), # system_wide parameter
|
||||||
),
|
),
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
required_if=[('state', 'present', ['value'])],
|
required_if=[('state', 'present', ['value'])],
|
||||||
|
|
|
||||||
|
|
@ -35,3 +35,5 @@ multiple_keys_comments: |
|
||||||
ssh-rsa DATA_BASIC 1@testing
|
ssh-rsa DATA_BASIC 1@testing
|
||||||
# I like adding comments yo-dude-this-is-not-a-key INVALID_DATA 2@testing
|
# I like adding comments yo-dude-this-is-not-a-key INVALID_DATA 2@testing
|
||||||
ecdsa-sha2-nistp521 ECDSA_DATA 4@testing
|
ecdsa-sha2-nistp521 ECDSA_DATA 4@testing
|
||||||
|
|
||||||
|
key_path: /tmp/id_rsa.pub
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
---
|
||||||
|
- name: Create key file for test
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: "{{ key_path }}"
|
||||||
|
content: "{{ rsa_key_basic }}"
|
||||||
|
mode: "0600"
|
||||||
|
|
||||||
|
- name: Add key using path
|
||||||
|
ansible.posix.authorized_key:
|
||||||
|
user: root
|
||||||
|
key: file://{{ key_path }}
|
||||||
|
state: present
|
||||||
|
path: "{{ output_dir | expanduser }}/authorized_keys"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Assert that the key was added
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- result.changed == true
|
||||||
|
|
||||||
|
- name: Add key using path again
|
||||||
|
ansible.posix.authorized_key:
|
||||||
|
user: root
|
||||||
|
key: file://{{ key_path }}
|
||||||
|
state: present
|
||||||
|
path: "{{ output_dir | expanduser }}/authorized_keys"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Assert that no changes were applied
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- result.changed == false
|
||||||
|
|
@ -31,3 +31,6 @@
|
||||||
|
|
||||||
- name: Test for the management of comments with key
|
- name: Test for the management of comments with key
|
||||||
ansible.builtin.import_tasks: comments.yml
|
ansible.builtin.import_tasks: comments.yml
|
||||||
|
|
||||||
|
- name: Test for specifying key as a path
|
||||||
|
ansible.builtin.import_tasks: check_path.yml
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue