Skip to content

Commit

Permalink
[ssh_config] Add support for ControlMaster (#7456)
Browse files Browse the repository at this point in the history
* [ssh_config] Add support for ControlMaster

* Create separate function to convert bool

* Allow str values with yes/no options to also use bool

(cherry picked from commit c2f08c5)
  • Loading branch information
mering authored and patchback[bot] committed Nov 11, 2023
1 parent 4b84127 commit 2679029
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 6 deletions.
2 changes: 2 additions & 0 deletions changelogs/fragments/7456-add-ssh-control-master.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
minor_changes:
- ssh_config - adds ``controlmaster``, ``controlpath`` and ``controlpersist`` parameters (https://github.com/ansible-collections/community.general/pull/7456).
46 changes: 40 additions & 6 deletions plugins/modules/ssh_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,22 @@
- Sets the C(HostKeyAlgorithms) option.
type: str
version_added: 6.1.0
controlmaster:
description:
- Sets the C(ControlMaster) option.
choices: [ 'yes', 'no', 'ask', 'auto', 'autoask' ]
type: str
version_added: 8.1.0
controlpath:
description:
- Sets the C(ControlPath) option.
type: str
version_added: 8.1.0
controlpersist:
description:
- Sets the C(ControlPersist) option.
type: str
version_added: 8.1.0
requirements:
- paramiko
'''
Expand Down Expand Up @@ -177,6 +193,22 @@
from ansible_collections.community.general.plugins.module_utils.ssh import determine_config_file


def convert_bool(value):
if value is True:
return 'yes'
if value is False:
return 'no'
return None


def fix_bool_str(value):
if value == 'True':
return 'yes'
if value == 'False':
return 'no'
return value


class SSHConfig(object):
def __init__(self, module):
self.module = module
Expand Down Expand Up @@ -219,14 +251,12 @@ def ensure_state(self):
proxycommand=self.params.get('proxycommand'),
proxyjump=self.params.get('proxyjump'),
host_key_algorithms=self.params.get('host_key_algorithms'),
forward_agent=convert_bool(self.params.get('forward_agent')),
controlmaster=self.params.get('controlmaster'),
controlpath=self.params.get('controlpath'),
controlpersist=fix_bool_str(self.params.get('controlpersist')),
)

# Convert True / False to 'yes' / 'no' for usage in ssh_config
if self.params['forward_agent'] is True:
args['forward_agent'] = 'yes'
if self.params['forward_agent'] is False:
args['forward_agent'] = 'no'

config_changed = False
hosts_changed = []
hosts_change_diff = []
Expand Down Expand Up @@ -320,9 +350,13 @@ def main():
ssh_config_file=dict(default=None, type='path'),
state=dict(type='str', default='present', choices=['present', 'absent']),
strict_host_key_checking=dict(
type='str',
default=None,
choices=['yes', 'no', 'ask']
),
controlmaster=dict(type='str', default=None, choices=['yes', 'no', 'ask', 'auto', 'autoask']),
controlpath=dict(type='str', default=None),
controlpersist=dict(type='str', default=None),
user=dict(default=None, type='str'),
user_known_hosts_file=dict(type='str', default=None),
),
Expand Down
54 changes: 54 additions & 0 deletions tests/integration/targets/ssh_config/tasks/options.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
proxycommand: "ssh jumphost.example.com -W %h:%p"
forward_agent: true
host_key_algorithms: "+ssh-rsa"
controlmaster: "auto"
controlpath: "~/.ssh/sockets/%r@%h-%p"
controlpersist: yes
state: present
register: options_add
check_mode: true
Expand Down Expand Up @@ -45,6 +48,9 @@
proxycommand: "ssh jumphost.example.com -W %h:%p"
forward_agent: true
host_key_algorithms: "+ssh-rsa"
controlmaster: "auto"
controlpath: "~/.ssh/sockets/%r@%h-%p"
controlpersist: yes
state: present
register: options_add

Expand All @@ -63,6 +69,9 @@
proxycommand: "ssh jumphost.example.com -W %h:%p"
forward_agent: true
host_key_algorithms: "+ssh-rsa"
controlmaster: "auto"
controlpath: "~/.ssh/sockets/%r@%h-%p"
controlpersist: yes
state: present
register: options_add_again

Expand All @@ -85,6 +94,9 @@
- "'proxycommand ssh jumphost.example.com -W %h:%p' in slurp_ssh_config['content'] | b64decode"
- "'forwardagent yes' in slurp_ssh_config['content'] | b64decode"
- "'hostkeyalgorithms +ssh-rsa' in slurp_ssh_config['content'] | b64decode"
- "'controlmaster auto' in slurp_ssh_config['content'] | b64decode"
- "'controlpath ~/.ssh/sockets/%r@%h-%p' in slurp_ssh_config['content'] | b64decode"
- "'controlpersist yes' in slurp_ssh_config['content'] | b64decode"

- name: Options - Update host
community.general.ssh_config:
Expand All @@ -93,6 +105,9 @@
proxycommand: "ssh new-jumphost.example.com -W %h:%p"
forward_agent: false
host_key_algorithms: "+ssh-ed25519"
controlmaster: no
controlpath: "~/.ssh/new-sockets/%r@%h-%p"
controlpersist: "600"
state: present
register: options_update

Expand All @@ -113,6 +128,9 @@
proxycommand: "ssh new-jumphost.example.com -W %h:%p"
forward_agent: false
host_key_algorithms: "+ssh-ed25519"
controlmaster: no
controlpath: "~/.ssh/new-sockets/%r@%h-%p"
controlpersist: "600"
state: present
register: options_update

Expand All @@ -136,6 +154,9 @@
- "'proxycommand ssh new-jumphost.example.com -W %h:%p' in slurp_ssh_config['content'] | b64decode"
- "'forwardagent no' in slurp_ssh_config['content'] | b64decode"
- "'hostkeyalgorithms +ssh-ed25519' in slurp_ssh_config['content'] | b64decode"
- "'controlmaster no' in slurp_ssh_config['content'] | b64decode"
- "'controlpath ~/.ssh/new-sockets/%r@%h-%p' in slurp_ssh_config['content'] | b64decode"
- "'controlpersist 600' in slurp_ssh_config['content'] | b64decode"

- name: Options - Ensure no update in case option exist in ssh_config file but wasn't defined in playbook
community.general.ssh_config:
Expand Down Expand Up @@ -164,6 +185,9 @@
- "'proxycommand ssh new-jumphost.example.com -W %h:%p' in slurp_ssh_config['content'] | b64decode"
- "'forwardagent no' in slurp_ssh_config['content'] | b64decode"
- "'hostkeyalgorithms +ssh-ed25519' in slurp_ssh_config['content'] | b64decode"
- "'controlmaster no' in slurp_ssh_config['content'] | b64decode"
- "'controlpath ~/.ssh/new-sockets/%r@%h-%p' in slurp_ssh_config['content'] | b64decode"
- "'controlpersist 600' in slurp_ssh_config['content'] | b64decode"

- name: Debug
debug:
Expand Down Expand Up @@ -210,6 +234,9 @@
- "'proxycommand ssh new-jumphost.example.com -W %h:%p' not in slurp_ssh_config['content'] | b64decode"
- "'forwardagent no' not in slurp_ssh_config['content'] | b64decode"
- "'hostkeyalgorithms +ssh-ed25519' not in slurp_ssh_config['content'] | b64decode"
- "'controlmaster auto' not in slurp_ssh_config['content'] | b64decode"
- "'controlpath ~/.ssh/sockets/%r@%h-%p' not in slurp_ssh_config['content'] | b64decode"
- "'controlpersist yes' not in slurp_ssh_config['content'] | b64decode"

# Proxycommand and ProxyJump are mutually exclusive.
# Reset ssh_config before testing options with proxyjump
Expand All @@ -226,6 +253,9 @@
proxyjump: "jumphost.example.com"
forward_agent: true
host_key_algorithms: "+ssh-rsa"
controlmaster: "auto"
controlpath: "~/.ssh/sockets/%r@%h-%p"
controlpersist: yes
state: present
register: options_add
check_mode: true
Expand Down Expand Up @@ -255,6 +285,9 @@
proxyjump: "jumphost.example.com"
forward_agent: true
host_key_algorithms: "+ssh-rsa"
controlmaster: "auto"
controlpath: "~/.ssh/sockets/%r@%h-%p"
controlpersist: yes
state: present
register: options_add

Expand All @@ -273,6 +306,9 @@
proxyjump: "jumphost.example.com"
forward_agent: true
host_key_algorithms: "+ssh-rsa"
controlmaster: "auto"
controlpath: "~/.ssh/sockets/%r@%h-%p"
controlpersist: yes
state: present
register: options_add_again

Expand All @@ -295,6 +331,9 @@
- "'proxyjump jumphost.example.com' in slurp_ssh_config['content'] | b64decode"
- "'forwardagent yes' in slurp_ssh_config['content'] | b64decode"
- "'hostkeyalgorithms +ssh-rsa' in slurp_ssh_config['content'] | b64decode"
- "'controlmaster auto' in slurp_ssh_config['content'] | b64decode"
- "'controlpath ~/.ssh/sockets/%r@%h-%p' in slurp_ssh_config['content'] | b64decode"
- "'controlpersist yes' in slurp_ssh_config['content'] | b64decode"

- name: Options - Update host
community.general.ssh_config:
Expand All @@ -303,6 +342,9 @@
proxyjump: "new-jumphost.example.com"
forward_agent: false
host_key_algorithms: "+ssh-ed25519"
controlmaster: no
controlpath: "~/.ssh/new-sockets/%r@%h-%p"
controlpersist: "600"
state: present
register: options_update

Expand All @@ -323,6 +365,9 @@
proxyjump: "new-jumphost.example.com"
forward_agent: false
host_key_algorithms: "+ssh-ed25519"
controlmaster: no
controlpath: "~/.ssh/new-sockets/%r@%h-%p"
controlpersist: "600"
state: present
register: options_update

Expand All @@ -346,6 +391,9 @@
- "'proxyjump new-jumphost.example.com' in slurp_ssh_config['content'] | b64decode"
- "'forwardagent no' in slurp_ssh_config['content'] | b64decode"
- "'hostkeyalgorithms +ssh-ed25519' in slurp_ssh_config['content'] | b64decode"
- "'controlmaster no' in slurp_ssh_config['content'] | b64decode"
- "'controlpath ~/.ssh/new-sockets/%r@%h-%p' in slurp_ssh_config['content'] | b64decode"
- "'controlpersist 600' in slurp_ssh_config['content'] | b64decode"

- name: Options - Ensure no update in case option exist in ssh_config file but wasn't defined in playbook
community.general.ssh_config:
Expand Down Expand Up @@ -374,6 +422,9 @@
- "'proxyjump new-jumphost.example.com' in slurp_ssh_config['content'] | b64decode"
- "'forwardagent no' in slurp_ssh_config['content'] | b64decode"
- "'hostkeyalgorithms +ssh-ed25519' in slurp_ssh_config['content'] | b64decode"
- "'controlmaster no' in slurp_ssh_config['content'] | b64decode"
- "'controlpath ~/.ssh/new-sockets/%r@%h-%p' in slurp_ssh_config['content'] | b64decode"
- "'controlpersist 600' in slurp_ssh_config['content'] | b64decode"

- name: Debug
debug:
Expand Down Expand Up @@ -420,3 +471,6 @@
- "'proxyjump new-jumphost.example.com' not in slurp_ssh_config['content'] | b64decode"
- "'forwardagent no' not in slurp_ssh_config['content'] | b64decode"
- "'hostkeyalgorithms +ssh-ed25519' not in slurp_ssh_config['content'] | b64decode"
- "'controlmaster auto' not in slurp_ssh_config['content'] | b64decode"
- "'controlpath ~/.ssh/sockets/%r@%h-%p' not in slurp_ssh_config['content'] | b64decode"
- "'controlpersist yes' not in slurp_ssh_config['content'] | b64decode"

0 comments on commit 2679029

Please sign in to comment.