diff --git a/apps/accounts/automations/change_secret/host/aix/main.yml b/apps/accounts/automations/change_secret/host/aix/main.yml index 761a9c2c1..afb7b0443 100644 --- a/apps/accounts/automations/change_secret/host/aix/main.yml +++ b/apps/accounts/automations/change_secret/host/aix/main.yml @@ -79,7 +79,7 @@ login_password: "{{ account.secret }}" login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" - gateway_args: "{{ jms_asset.ansible_ssh_common_args | default('') }}" + gateway_args: "{{ jms_asset.ansible_ssh_common_args | default(None) }}" become: "{{ account.become.ansible_become | default(False) }}" become_method: su become_user: "{{ account.become.ansible_user | default('') }}" @@ -95,7 +95,7 @@ login_port: "{{ jms_asset.port }}" login_user: "{{ account.username }}" login_private_key_path: "{{ account.private_key_path }}" - gateway_args: "{{ jms_asset.ansible_ssh_common_args | default('') }}" + gateway_args: "{{ jms_asset.ansible_ssh_common_args | default(None) }}" old_ssh_version: "{{ jms_asset.old_ssh_version | default(False) }}" when: account.secret_type == "ssh_key" delegate_to: localhost diff --git a/apps/accounts/automations/change_secret/host/posix/main.yml b/apps/accounts/automations/change_secret/host/posix/main.yml index d166de81f..e58e8422e 100644 --- a/apps/accounts/automations/change_secret/host/posix/main.yml +++ b/apps/accounts/automations/change_secret/host/posix/main.yml @@ -79,7 +79,7 @@ login_password: "{{ account.secret }}" login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" - gateway_args: "{{ jms_asset.ansible_ssh_common_args | default('') }}" + gateway_args: "{{ jms_asset.ansible_ssh_common_args | default(None) }}" become: "{{ account.become.ansible_become | default(False) }}" become_method: su become_user: "{{ account.become.ansible_user | default('') }}" @@ -95,7 +95,7 @@ login_port: "{{ jms_asset.port }}" login_user: "{{ account.username }}" login_private_key_path: "{{ account.private_key_path }}" - gateway_args: "{{ jms_asset.ansible_ssh_common_args | default('') }}" + gateway_args: "{{ jms_asset.ansible_ssh_common_args | default(None) }}" old_ssh_version: "{{ jms_asset.old_ssh_version | default(False) }}" when: account.secret_type == "ssh_key" delegate_to: localhost diff --git a/apps/accounts/automations/change_secret/host/windows_rdp_verify/main.yml b/apps/accounts/automations/change_secret/host/windows_rdp_verify/main.yml index e1ced1359..31da190ef 100644 --- a/apps/accounts/automations/change_secret/host/windows_rdp_verify/main.yml +++ b/apps/accounts/automations/change_secret/host/windows_rdp_verify/main.yml @@ -25,11 +25,11 @@ - name: Verify password (pyfreerdp) rdp_ping: - login_host: "{{ jms_asset.address }}" + login_host: "{{ jms_asset.origin_address }}" login_port: "{{ jms_asset.protocols | selectattr('name', 'equalto', 'rdp') | map(attribute='port') | first }}" login_user: "{{ account.username }}" login_password: "{{ account.secret }}" login_secret_type: "{{ account.secret_type }}" - login_private_key_path: "{{ account.private_key_path }}" + gateway_args: "{{ jms_gateway | default(None) }}" when: account.secret_type == "password" delegate_to: localhost diff --git a/apps/accounts/automations/push_account/host/aix/main.yml b/apps/accounts/automations/push_account/host/aix/main.yml index 8c03c07f3..fd33c5f8c 100644 --- a/apps/accounts/automations/push_account/host/aix/main.yml +++ b/apps/accounts/automations/push_account/host/aix/main.yml @@ -79,7 +79,7 @@ login_password: "{{ account.secret }}" login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" - gateway_args: "{{ jms_asset.ansible_ssh_common_args | default('') }}" + gateway_args: "{{ jms_asset.ansible_ssh_common_args | default(None) }}" become: "{{ account.become.ansible_become | default(False) }}" become_method: su become_user: "{{ account.become.ansible_user | default('') }}" @@ -95,7 +95,7 @@ login_port: "{{ jms_asset.port }}" login_user: "{{ account.username }}" login_private_key_path: "{{ account.private_key_path }}" - gateway_args: "{{ jms_asset.ansible_ssh_common_args | default('') }}" + gateway_args: "{{ jms_asset.ansible_ssh_common_args | default(None) }}" old_ssh_version: "{{ jms_asset.old_ssh_version | default(False) }}" when: account.secret_type == "ssh_key" delegate_to: localhost diff --git a/apps/accounts/automations/push_account/host/posix/main.yml b/apps/accounts/automations/push_account/host/posix/main.yml index 8bc433f5a..83aa34206 100644 --- a/apps/accounts/automations/push_account/host/posix/main.yml +++ b/apps/accounts/automations/push_account/host/posix/main.yml @@ -79,7 +79,7 @@ login_password: "{{ account.secret }}" login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" - gateway_args: "{{ jms_asset.ansible_ssh_common_args | default('') }}" + gateway_args: "{{ jms_asset.ansible_ssh_common_args | default(None) }}" become: "{{ account.become.ansible_become | default(False) }}" become_method: su become_user: "{{ account.become.ansible_user | default('') }}" @@ -95,7 +95,7 @@ login_port: "{{ jms_asset.port }}" login_user: "{{ account.username }}" login_private_key_path: "{{ account.private_key_path }}" - gateway_args: "{{ jms_asset.ansible_ssh_common_args | default('') }}" + gateway_args: "{{ jms_asset.ansible_ssh_common_args | default(None) }}" old_ssh_version: "{{ jms_asset.old_ssh_version | default(False) }}" when: account.secret_type == "ssh_key" delegate_to: localhost diff --git a/apps/accounts/automations/push_account/host/windows_rdp_verify/main.yml b/apps/accounts/automations/push_account/host/windows_rdp_verify/main.yml index 29f4fb022..e15b5889e 100644 --- a/apps/accounts/automations/push_account/host/windows_rdp_verify/main.yml +++ b/apps/accounts/automations/push_account/host/windows_rdp_verify/main.yml @@ -25,11 +25,11 @@ - name: Verify password (pyfreerdp) rdp_ping: - login_host: "{{ jms_asset.address }}" + login_host: "{{ jms_asset.origin_address }}" login_port: "{{ jms_asset.protocols | selectattr('name', 'equalto', 'rdp') | map(attribute='port') | first }}" login_user: "{{ account.username }}" login_password: "{{ account.secret }}" login_secret_type: "{{ account.secret_type }}" - login_private_key_path: "{{ account.private_key_path }}" + gateway_args: "{{ jms_gateway | default(None) }}" when: account.secret_type == "password" delegate_to: localhost diff --git a/apps/accounts/automations/verify_account/custom/rdp/main.yml b/apps/accounts/automations/verify_account/custom/rdp/main.yml index 2d8bcb883..33ee8282b 100644 --- a/apps/accounts/automations/verify_account/custom/rdp/main.yml +++ b/apps/accounts/automations/verify_account/custom/rdp/main.yml @@ -13,4 +13,3 @@ login_user: "{{ account.username }}" login_password: "{{ account.secret }}" login_secret_type: "{{ account.secret_type }}" - login_private_key_path: "{{ account.private_key_path }}" diff --git a/apps/assets/automations/ping/custom/rdp/main.yml b/apps/assets/automations/ping/custom/rdp/main.yml index c0808e976..bcf07c15c 100644 --- a/apps/assets/automations/ping/custom/rdp/main.yml +++ b/apps/assets/automations/ping/custom/rdp/main.yml @@ -13,4 +13,3 @@ login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" login_secret_type: "{{ jms_account.secret_type }}" - login_private_key_path: "{{ jms_account.private_key_path }}" diff --git a/apps/libs/ansible/modules/rdp_ping.py b/apps/libs/ansible/modules/rdp_ping.py index 6098f155d..bfbac2211 100644 --- a/apps/libs/ansible/modules/rdp_ping.py +++ b/apps/libs/ansible/modules/rdp_ping.py @@ -36,7 +36,8 @@ conn_err_msg: ''' import pyfreerdp -from typing import NamedTuple +import multiprocessing +from sshtunnel import SSHTunnelForwarder from ansible.module_utils.basic import AnsibleModule @@ -44,12 +45,6 @@ from ansible.module_utils.basic import AnsibleModule # Module execution. # -class Param(NamedTuple): - hostname: str - port: int - username: str - password: str - def common_argument_spec(): options = dict( @@ -58,37 +53,102 @@ def common_argument_spec(): login_user=dict(type='str', required=False, default='root'), login_password=dict(type='str', required=False, no_log=True), login_secret_type=dict(type='str', required=False, default='password'), - login_private_key_path=dict(type='str', required=False, no_log=True), + gateway_args=dict(type='dict', required=False, default=None), ) return options -def main(): - options = common_argument_spec() - module = AnsibleModule(argument_spec=options, supports_check_mode=True) - result = {'changed': False, 'is_available': False} +class RDPConnectionManager: - secret_type = module.params['login_secret_type'] - if secret_type != 'password': - module.fail_json( - msg=f'The current ansible does not support \ - the verification method for {secret_type} types.' + def __init__(self, module_params): + self.params = module_params + self.ssh_tunnel = None + self.connection_details = self.build_connection_details() + self.result_queue = multiprocessing.Queue() + + def build_connection_details(self): + connection_details = { + 'hostname': self.params['login_host'], + 'port': self.params['login_port'], + 'username': self.params['username'], + 'password': self.params['password'] + } + return connection_details + + def setup_ssh_tunnel(self): + gateway_args = self.params['gateway_args'] or {} + if not gateway_args: + return + + tunnel = SSHTunnelForwarder( + (gateway_args['address'], gateway_args['port']), + ssh_username=gateway_args['username'], + ssh_password=gateway_args['secret'], + ssh_pkey=gateway_args['private_key_path'], + remote_bind_address=( + self.connection_details['hostname'], + self.connection_details['port'] + ) ) - return module.exit_json(**result) - params = Param( - hostname=module.params['login_host'], - port=module.params['login_port'], - username=module.params['login_user'], - password=module.params['login_password'] - ) + tunnel.start() + self.connection_details['hostname'] = '127.0.0.1' + self.connection_details['port'] = tunnel.local_bind_port + self.ssh_tunnel = tunnel - is_available = pyfreerdp.check_connectivity(*params, '', 0) + def close_ssh_tunnel(self): + if self.ssh_tunnel: + self.ssh_tunnel.stop() + + def prepare_connection(self): + self.setup_ssh_tunnel() + + def cleanup_connection(self): + self.close_ssh_tunnel() + + def check_rdp_connectivity(self): + connect_params = list(self.connection_details.values()) + ['', 0] + is_reachable = pyfreerdp.check_connectivity(*connect_params) + self.result_queue.put(is_reachable) + + def attempt_connection(self): + if self.params['login_secret_type'] != 'password': + error_message = f'unsupported authentication method: {self.params["login_secret_type"]}' + return False, error_message + + try: + self.prepare_connection() + + connection_process = multiprocessing.Process( + target=self.check_rdp_connectivity + ) + connection_process.start() + connection_process.join() + + is_reachable = self.result_queue.get() + self.cleanup_connection() + + if not is_reachable: + return False, 'RDP connection failed' + except Exception as ex: + return False, str(ex) + return True, '' + + +def main(): + argument_spec = common_argument_spec() + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True) + result = {'changed': False} + module_params = module.params + rdp_manager = RDPConnectionManager(module_params) + is_available, error_message = rdp_manager.attempt_connection() result['is_available'] = is_available + if not is_available: - module.fail_json(msg='Unable to connect to asset.') + module.fail_json(msg=f'Unable to connect to asset: {error_message}') + return module.exit_json(**result) if __name__ == '__main__': - main() + main() \ No newline at end of file diff --git a/apps/libs/ansible/modules_utils/custom_common.py b/apps/libs/ansible/modules_utils/custom_common.py index f27446e9e..c70fba275 100644 --- a/apps/libs/ansible/modules_utils/custom_common.py +++ b/apps/libs/ansible/modules_utils/custom_common.py @@ -151,10 +151,8 @@ class SSHClient: gateway_server = self.gateway_server if not gateway_server: return - try: - gateway_server.stop() - except Exception: - pass + + gateway_server.stop() def before_runner_start(self): self.local_gateway_prepare() diff --git a/apps/ops/ansible/inventory.py b/apps/ops/ansible/inventory.py index fde3f290b..09bfd0f39 100644 --- a/apps/ops/ansible/inventory.py +++ b/apps/ops/ansible/inventory.py @@ -187,6 +187,7 @@ class JMSInventory: 'protocol': protocol.name, 'port': protocol.port, 'spec_info': asset.spec_info, 'secret_info': secret_info, 'protocols': [{'name': p.name, 'port': p.port} for p in protocols], + 'origin_address': asset.address }, 'jms_account': { 'id': str(account.id), 'username': account.username,