From 54e97e5e73416788ee9091b8c9c984767e7f6ae4 Mon Sep 17 00:00:00 2001 From: Tobias Richter Date: Wed, 4 Dec 2019 22:56:27 +0100 Subject: [PATCH 1/7] Connect http and https port to conga_config values --- defaults/main.yml | 4 ++-- tasks/response-test.yml | 2 ++ tasks/ssl-enforce-test.yml | 2 ++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 0a4009c..81009c0 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -46,8 +46,8 @@ conga_aemdst_curl_host: "{{ inventory_hostname }}" # Allows to overwrite/control the host resolve mechanism of curl conga_aemdst_curl_resolve: - host: "{{ conga_aemdst_curl_url | urlsplit('hostname') }}" - port: "80" + port: "{{ conga_aemdst_curl_server_port }}" address: "127.0.0.1" - host: "{{ conga_aemdst_curl_url | urlsplit('hostname') }}" - port: "443" + port: "{{ conga_aemdst_curl_server_port_ssl }}" address: "127.0.0.1" diff --git a/tasks/response-test.yml b/tasks/response-test.yml index a504c67..230075d 100644 --- a/tasks/response-test.yml +++ b/tasks/response-test.yml @@ -32,6 +32,8 @@ include_tasks: curl.yml vars: conga_aemdst_curl_url: "{{ _response_test_initial_url }}" + conga_aemdst_curl_server_port: "{{ response_test_config.httpd.serverPort | default(80) }}" + conga_aemdst_curl_server_port_ssl: "{{ response_test_config.httpd.serverPortSsl | default(443) }}" conga_aemdst_curl_expected_url: "{{ _response_test_expected_result_url }}" conga_aemdst_curl_expected_url_test_lazy: "{{ response_test_lazy }}" conga_aemdst_curl_follow_redirects_expected_http_code: "{{ response_test_expected_http_code }}" diff --git a/tasks/ssl-enforce-test.yml b/tasks/ssl-enforce-test.yml index a4897fe..50d6a08 100644 --- a/tasks/ssl-enforce-test.yml +++ b/tasks/ssl-enforce-test.yml @@ -2,6 +2,8 @@ include_tasks: curl.yml vars: conga_aemdst_curl_url: "http://{{ enforce_ssl_config.httpd.serverName }}{{ _initial_port_suffix }}" + conga_aemdst_curl_server_port: "{{ enforce_ssl_config.httpd.serverPort | default(80) }}" + conga_aemdst_curl_server_port_ssl: "{{ enforce_ssl_config.httpd.serverPortSsl | default(443) }}" conga_aemdst_curl_expected_url: "https://{{ enforce_ssl_config.httpd.serverNameSsl }}{{ _expected_port_suffix }}/" conga_aemdst_curl_expected_url_test_lazy: "{{ conga_aemdst_ssl_enforce_lazy }}" conga_aemdst_curl_follow_redirects: "{{ conga_aemdst_ssl_enforce_follow_redirects }}" From cd85e5fcee04aec9bc83d34e82fa3d8ea8396eee Mon Sep 17 00:00:00 2001 From: Tobias Richter Date: Thu, 5 Dec 2019 21:22:40 +0100 Subject: [PATCH 2/7] Fix custom listen address, Moved evaluation to own 'conga_aemdst_facts' action plugin --- action_plugins/conga_aemdst_facts.py | 127 +++++++++++++++++++++++++++ defaults/main.yml | 4 +- tasks/main.yml | 19 ---- tasks/response-test.yml | 47 ++++------ tasks/ssl-enforce-test.yml | 21 +++-- 5 files changed, 162 insertions(+), 56 deletions(-) create mode 100644 action_plugins/conga_aemdst_facts.py diff --git a/action_plugins/conga_aemdst_facts.py b/action_plugins/conga_aemdst_facts.py new file mode 100644 index 0000000..124244e --- /dev/null +++ b/action_plugins/conga_aemdst_facts.py @@ -0,0 +1,127 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +from __future__ import (absolute_import, division, print_function) + +__metaclass__ = type + +import os +import re + +from ansible.module_utils._text import to_native +from ansible.plugins.action import ActionBase +from ansible.errors import AnsibleOptionsError + +try: + from __main__ import display +except ImportError: + from ansible.utils.display import Display + + display = Display() + + +class ActionModule(ActionBase): + TRANSFERS_FILES = False + + def __init__(self, task, connection, play_context, loader, templar, shared_loader_obj): + super(ActionModule, self).__init__(task, connection, play_context, loader, templar, shared_loader_obj) + self._task_vars = None + + def run(self, tmp=None, task_vars=None): + if task_vars is None: + task_vars = dict() + + result = super(ActionModule, self).run(tmp, task_vars) + + self._task_vars = task_vars + + try: + # Get conga_facts based config (whole or tenant config) + config = self._get_arg_or_var('conga_config') + + except AnsibleOptionsError as err: + return self._fail_result(result, err.message) + + httpd_cfg = config.get("httpd", {}) + ssl_cfg = httpd_cfg.get("ssl", {}) + ssl_enforce = ssl_cfg.get("enforce", False) + + ssl_offloading_cfg = ssl_cfg.get("offloading", {}) + ssl_offloading_enabled = ssl_offloading_cfg.get("enabled", False) + + # set defaults + server_listen_address = httpd_cfg.get("serverListenAddressSsl", "127.0.0.1") + server_listen_address_ssl = httpd_cfg.get("serverListenAddressSsl", "127.0.0.1") + + server_name = httpd_cfg.get("serverName", None) + server_name_ssl = httpd_cfg.get("serverNameSsl", None) + + listen_port = httpd_cfg.get("serverPort", 80) + listen_port_ssl = httpd_cfg.get("serverPortSsl", 443) + + initial_port = listen_port + expected_port = listen_port + + response_test_headers = [] + + # when ssl is enforced and not offloaded we are expecting the ssl port + if ssl_enforce and not ssl_offloading_enabled: + expected_port = listen_port_ssl + + listen_port_suffix = "" if listen_port == 80 else ":{}".format(initial_port) + listen_port_suffix_ssl = "" if listen_port_ssl == 443 else ":{}".format(expected_port) + + ssl_enforce_initial_url = "http://{}{}".format(server_name, listen_port_suffix) + ssl_enforce_expected_url = "https://{}{}/".format(server_name_ssl, listen_port_suffix_ssl) + + response_test_initial_url = ssl_enforce_initial_url + response_test_expected_url = response_test_initial_url + "/" + + if ssl_enforce: + if ssl_offloading_enabled: + # when ssl is offloaded we have to simulate a forwareded https request + response_test_headers.append("X-Forwarded-Proto: https") + else: + # when ssl is not offloaded we are expecting an ssl upgrade + response_test_expected_url = ssl_enforce_expected_url + + results = { + # "config": config, + "server_listen_address": server_listen_address, + "server_listen_address_ssl": server_listen_address_ssl, + "listen_port": listen_port, + "listen_port_ssl": listen_port_ssl, + "initial_port": initial_port, + "expected_port": expected_port, + "listen_port_suffix": listen_port_suffix, + "listen_port_suffix_ssl": listen_port_suffix_ssl, + "ssl_enforce_initial_url": ssl_enforce_initial_url, + "ssl_enforce_expected_url": ssl_enforce_expected_url, + "response_test_headers": response_test_headers, + "response_test_initial_url": response_test_initial_url, + "response_test_expected_url": response_test_expected_url + } + + result["ansible_facts"] = { + "conga_aemdst_config": results, + } + + # Always display resolved role and mapping + display.display( + "[[%s] => %s" % + (task_vars['inventory_hostname'], results)) + + return result + + @staticmethod + def _fail_result(result, message): + result['failed'] = True + result['msg'] = message + return result + + def _get_arg_or_var(self, name, default=None, is_required=True): + ret = self._task.args.get(name, self._task_vars.get(name, default)) + if is_required and not ret: + raise AnsibleOptionsError("parameter %s is required" % name) + else: + return ret diff --git a/defaults/main.yml b/defaults/main.yml index 81009c0..49a0657 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -47,7 +47,7 @@ conga_aemdst_curl_host: "{{ inventory_hostname }}" conga_aemdst_curl_resolve: - host: "{{ conga_aemdst_curl_url | urlsplit('hostname') }}" port: "{{ conga_aemdst_curl_server_port }}" - address: "127.0.0.1" + address: "{{ conga_aemdst_curl_resolve_ip }}" - host: "{{ conga_aemdst_curl_url | urlsplit('hostname') }}" port: "{{ conga_aemdst_curl_server_port_ssl }}" - address: "127.0.0.1" + address: "{{ conga_aemdst_curl_resolve_ip_ssl }}" diff --git a/tasks/main.yml b/tasks/main.yml index dd76224..e96c698 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -1,22 +1,3 @@ -- name: "Set default port facts" - set_fact: - _initial_port_suffix: "" - _expected_port_suffix: "" - -- name: "Set custom initial port suffix" - set_fact: - _initial_port_suffix: ":{{ conga_config.httpd.serverPort }}" - _expected_port_suffix: ":{{ conga_config.httpd.serverPort }}" - when: - - conga_config.httpd.serverPort != 80 - -- name: "Set custom expected port suffix (http)" - set_fact: - _expected_port_suffix: ":{{ conga_config.httpd.serverPortSsl }}" - when: - - conga_config.httpd.serverPortSsl != 443 - - conga_config.httpd.ssl.enforce - - name: "Run aem-publish tests" include_tasks: aem-publish-tests.yml when: "'aem-publish' in conga_variants" diff --git a/tasks/response-test.yml b/tasks/response-test.yml index 230075d..5467bb5 100644 --- a/tasks/response-test.yml +++ b/tasks/response-test.yml @@ -1,41 +1,28 @@ -- name: "Set default (non-ssl) facts" - set_fact: - _response_test_initial_url: "http://{{ response_test_config.httpd.serverName }}{{ _initial_port_suffix }}" - _response_test_expected_result_url: "http://{{ response_test_config.httpd.serverName }}{{ _expected_port_suffix }}/" - _response_test_headers: [] +- name: "Evaluate conga_aemdst_facts." + conga_aemdst_facts: + conga_config: "{{ response_test_config }}" -# When ssl is enforced and we have no ssl offloading we expect an upgrade to https during the response test. -- name: "Set ssl facts." - set_fact: - _response_test_expected_result_url: - "https://{{ response_test_config.httpd.serverNameSsl }}{{ _expected_port_suffix }}/" - when: - - response_test_config.httpd.ssl.enforce - - not response_test_config.httpd.ssl.offloading.enabled # when ssl is offloaded we are not expecting an https upgrade - -# When ssl is enforced but offloading is enabled we have to send the "X-Forwarded-Proto" header for the response test -- name: "Set ssl-offloading facts." - set_fact: - _response_test_headers: - - 'X-Forwarded-Proto: https' - when: - - response_test_config.httpd.ssl.enforce - - response_test_config.httpd.ssl.offloading.enabled +- name: "Output conga_aemdst_config." + debug: + var: conga_aemdst_config + verbosity: 1 - debug: msg: - - "_response_test_initial_url : {{ _response_test_initial_url }}" - - "_response_test_expected_result_url : {{ _response_test_expected_result_url }}" - - "response_test_expected_http_code : {{ response_test_expected_http_code }}" + - "initial url : {{ conga_aemdst_config.response_test_initial_url }}" + - "expected url : {{ conga_aemdst_config.response_test_expected_url }}" + - "response_test_expected_http_code : {{ response_test_expected_http_code }}" - name: "Check for {{ aemdst_response_test_expected_http_code }} response when following redirects" include_tasks: curl.yml vars: - conga_aemdst_curl_url: "{{ _response_test_initial_url }}" - conga_aemdst_curl_server_port: "{{ response_test_config.httpd.serverPort | default(80) }}" - conga_aemdst_curl_server_port_ssl: "{{ response_test_config.httpd.serverPortSsl | default(443) }}" - conga_aemdst_curl_expected_url: "{{ _response_test_expected_result_url }}" + conga_aemdst_curl_url: "{{ conga_aemdst_config.response_test_initial_url }}" + conga_aemdst_curl_server_port: "{{ conga_aemdst_config.listen_port }}" + conga_aemdst_curl_server_port_ssl: "{{ conga_aemdst_config.listen_port_ssl }}" + conga_aemdst_curl_resolve_ip: "{{ conga_aemdst_config.server_listen_address }}" + conga_aemdst_curl_resolve_ip_ssl: "{{ conga_aemdst_config.server_listen_address_ssl }}" + conga_aemdst_curl_expected_url: "{{ conga_aemdst_config.response_test_expected_url }}" conga_aemdst_curl_expected_url_test_lazy: "{{ response_test_lazy }}" conga_aemdst_curl_follow_redirects_expected_http_code: "{{ response_test_expected_http_code }}" conga_aemdst_curl_follow_redirects: "{{ response_test_follow_redirects }}" - conga_aemdst_curl_headers: "{{ _response_test_headers }}" + conga_aemdst_curl_headers: "{{ conga_aemdst_config.response_test_headers }}" diff --git a/tasks/ssl-enforce-test.yml b/tasks/ssl-enforce-test.yml index 50d6a08..78034bd 100644 --- a/tasks/ssl-enforce-test.yml +++ b/tasks/ssl-enforce-test.yml @@ -1,9 +1,20 @@ -- name: "Run enforce ssl test for {{ enforce_ssl_config.httpd.serverName }}" +- name: "Evaluate conga_aemdst_facts." + conga_aemdst_facts: + conga_config: "{{ enforce_ssl_config }}" + +- name: "Output conga_aemdst_config." + debug: + var: conga_aemdst_config + verbosity: 1 + +- name: "Run enforce ssl test for {{ enforce_ssl_config.httpd.serverName }}." include_tasks: curl.yml vars: - conga_aemdst_curl_url: "http://{{ enforce_ssl_config.httpd.serverName }}{{ _initial_port_suffix }}" - conga_aemdst_curl_server_port: "{{ enforce_ssl_config.httpd.serverPort | default(80) }}" - conga_aemdst_curl_server_port_ssl: "{{ enforce_ssl_config.httpd.serverPortSsl | default(443) }}" - conga_aemdst_curl_expected_url: "https://{{ enforce_ssl_config.httpd.serverNameSsl }}{{ _expected_port_suffix }}/" + conga_aemdst_curl_url: "{{ conga_aemdst_config.ssl_enforce_initial_url }}" + conga_aemdst_curl_server_port: "{{ conga_aemdst_config.listen_port }}" + conga_aemdst_curl_server_port_ssl: "{{ conga_aemdst_config.listen_port_ssl }}" + conga_aemdst_curl_expected_url: "{{ conga_aemdst_config.ssl_enforce_expected_url }}" conga_aemdst_curl_expected_url_test_lazy: "{{ conga_aemdst_ssl_enforce_lazy }}" conga_aemdst_curl_follow_redirects: "{{ conga_aemdst_ssl_enforce_follow_redirects }}" + conga_aemdst_curl_resolve_ip: "{{ conga_aemdst_config.server_listen_address }}" + conga_aemdst_curl_resolve_ip_ssl: "{{ conga_aemdst_config.server_listen_address_ssl }}" \ No newline at end of file From d3bdea3c6b7ef6a007c65f7e7b5998be09a39388 Mon Sep 17 00:00:00 2001 From: Tobias Richter Date: Thu, 5 Dec 2019 21:23:40 +0100 Subject: [PATCH 3/7] Add .pyc files to ignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index ba48aa0..4ff82cc 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,4 @@ npm-debug.log *.sublime-* *nbactions*.xml .temp/ +*.pyc From ba020f6b7202044a67f32d3760c133c756936559 Mon Sep 17 00:00:00 2001 From: Tobias Richter Date: Thu, 5 Dec 2019 21:31:48 +0100 Subject: [PATCH 4/7] Indent with two spaces --- action_plugins/conga_aemdst_facts.py | 214 +++++++++++++-------------- 1 file changed, 107 insertions(+), 107 deletions(-) diff --git a/action_plugins/conga_aemdst_facts.py b/action_plugins/conga_aemdst_facts.py index 124244e..746eea7 100644 --- a/action_plugins/conga_aemdst_facts.py +++ b/action_plugins/conga_aemdst_facts.py @@ -13,115 +13,115 @@ from ansible.errors import AnsibleOptionsError try: - from __main__ import display + from __main__ import display except ImportError: - from ansible.utils.display import Display + from ansible.utils.display import Display - display = Display() + display = Display() class ActionModule(ActionBase): - TRANSFERS_FILES = False - - def __init__(self, task, connection, play_context, loader, templar, shared_loader_obj): - super(ActionModule, self).__init__(task, connection, play_context, loader, templar, shared_loader_obj) - self._task_vars = None - - def run(self, tmp=None, task_vars=None): - if task_vars is None: - task_vars = dict() - - result = super(ActionModule, self).run(tmp, task_vars) - - self._task_vars = task_vars - - try: - # Get conga_facts based config (whole or tenant config) - config = self._get_arg_or_var('conga_config') - - except AnsibleOptionsError as err: - return self._fail_result(result, err.message) - - httpd_cfg = config.get("httpd", {}) - ssl_cfg = httpd_cfg.get("ssl", {}) - ssl_enforce = ssl_cfg.get("enforce", False) - - ssl_offloading_cfg = ssl_cfg.get("offloading", {}) - ssl_offloading_enabled = ssl_offloading_cfg.get("enabled", False) - - # set defaults - server_listen_address = httpd_cfg.get("serverListenAddressSsl", "127.0.0.1") - server_listen_address_ssl = httpd_cfg.get("serverListenAddressSsl", "127.0.0.1") - - server_name = httpd_cfg.get("serverName", None) - server_name_ssl = httpd_cfg.get("serverNameSsl", None) - - listen_port = httpd_cfg.get("serverPort", 80) - listen_port_ssl = httpd_cfg.get("serverPortSsl", 443) - - initial_port = listen_port - expected_port = listen_port - - response_test_headers = [] - - # when ssl is enforced and not offloaded we are expecting the ssl port - if ssl_enforce and not ssl_offloading_enabled: - expected_port = listen_port_ssl - - listen_port_suffix = "" if listen_port == 80 else ":{}".format(initial_port) - listen_port_suffix_ssl = "" if listen_port_ssl == 443 else ":{}".format(expected_port) - - ssl_enforce_initial_url = "http://{}{}".format(server_name, listen_port_suffix) - ssl_enforce_expected_url = "https://{}{}/".format(server_name_ssl, listen_port_suffix_ssl) - - response_test_initial_url = ssl_enforce_initial_url - response_test_expected_url = response_test_initial_url + "/" - - if ssl_enforce: - if ssl_offloading_enabled: - # when ssl is offloaded we have to simulate a forwareded https request - response_test_headers.append("X-Forwarded-Proto: https") - else: - # when ssl is not offloaded we are expecting an ssl upgrade - response_test_expected_url = ssl_enforce_expected_url - - results = { - # "config": config, - "server_listen_address": server_listen_address, - "server_listen_address_ssl": server_listen_address_ssl, - "listen_port": listen_port, - "listen_port_ssl": listen_port_ssl, - "initial_port": initial_port, - "expected_port": expected_port, - "listen_port_suffix": listen_port_suffix, - "listen_port_suffix_ssl": listen_port_suffix_ssl, - "ssl_enforce_initial_url": ssl_enforce_initial_url, - "ssl_enforce_expected_url": ssl_enforce_expected_url, - "response_test_headers": response_test_headers, - "response_test_initial_url": response_test_initial_url, - "response_test_expected_url": response_test_expected_url - } - - result["ansible_facts"] = { - "conga_aemdst_config": results, - } - - # Always display resolved role and mapping - display.display( - "[[%s] => %s" % - (task_vars['inventory_hostname'], results)) - - return result - - @staticmethod - def _fail_result(result, message): - result['failed'] = True - result['msg'] = message - return result - - def _get_arg_or_var(self, name, default=None, is_required=True): - ret = self._task.args.get(name, self._task_vars.get(name, default)) - if is_required and not ret: - raise AnsibleOptionsError("parameter %s is required" % name) - else: - return ret + TRANSFERS_FILES = False + + def __init__(self, task, connection, play_context, loader, templar, shared_loader_obj): + super(ActionModule, self).__init__(task, connection, play_context, loader, templar, shared_loader_obj) + self._task_vars = None + + def run(self, tmp=None, task_vars=None): + if task_vars is None: + task_vars = dict() + + result = super(ActionModule, self).run(tmp, task_vars) + + self._task_vars = task_vars + + try: + # Get conga_facts based config (whole or tenant config) + config = self._get_arg_or_var('conga_config') + + except AnsibleOptionsError as err: + return self._fail_result(result, err.message) + + httpd_cfg = config.get("httpd", {}) + ssl_cfg = httpd_cfg.get("ssl", {}) + ssl_enforce = ssl_cfg.get("enforce", False) + + ssl_offloading_cfg = ssl_cfg.get("offloading", {}) + ssl_offloading_enabled = ssl_offloading_cfg.get("enabled", False) + + # set defaults + server_listen_address = httpd_cfg.get("serverListenAddressSsl", "127.0.0.1") + server_listen_address_ssl = httpd_cfg.get("serverListenAddressSsl", "127.0.0.1") + + server_name = httpd_cfg.get("serverName", None) + server_name_ssl = httpd_cfg.get("serverNameSsl", None) + + listen_port = httpd_cfg.get("serverPort", 80) + listen_port_ssl = httpd_cfg.get("serverPortSsl", 443) + + initial_port = listen_port + expected_port = listen_port + + response_test_headers = [] + + # when ssl is enforced and not offloaded we are expecting the ssl port + if ssl_enforce and not ssl_offloading_enabled: + expected_port = listen_port_ssl + + listen_port_suffix = "" if listen_port == 80 else ":{}".format(initial_port) + listen_port_suffix_ssl = "" if listen_port_ssl == 443 else ":{}".format(expected_port) + + ssl_enforce_initial_url = "http://{}{}".format(server_name, listen_port_suffix) + ssl_enforce_expected_url = "https://{}{}/".format(server_name_ssl, listen_port_suffix_ssl) + + response_test_initial_url = ssl_enforce_initial_url + response_test_expected_url = response_test_initial_url + "/" + + if ssl_enforce: + if ssl_offloading_enabled: + # when ssl is offloaded we have to simulate a forwareded https request + response_test_headers.append("X-Forwarded-Proto: https") + else: + # when ssl is not offloaded we are expecting an ssl upgrade + response_test_expected_url = ssl_enforce_expected_url + + results = { + # "config": config, + "server_listen_address": server_listen_address, + "server_listen_address_ssl": server_listen_address_ssl, + "listen_port": listen_port, + "listen_port_ssl": listen_port_ssl, + "initial_port": initial_port, + "expected_port": expected_port, + "listen_port_suffix": listen_port_suffix, + "listen_port_suffix_ssl": listen_port_suffix_ssl, + "ssl_enforce_initial_url": ssl_enforce_initial_url, + "ssl_enforce_expected_url": ssl_enforce_expected_url, + "response_test_headers": response_test_headers, + "response_test_initial_url": response_test_initial_url, + "response_test_expected_url": response_test_expected_url + } + + result["ansible_facts"] = { + "conga_aemdst_config": results, + } + + # Always display resolved role and mapping + display.display( + "[[%s] => %s" % + (task_vars['inventory_hostname'], results)) + + return result + + @staticmethod + def _fail_result(result, message): + result['failed'] = True + result['msg'] = message + return result + + def _get_arg_or_var(self, name, default=None, is_required=True): + ret = self._task.args.get(name, self._task_vars.get(name, default)) + if is_required and not ret: + raise AnsibleOptionsError("parameter %s is required" % name) + else: + return ret From 5353c67dd460aa7ffd3f2dee92312b45bf08b338 Mon Sep 17 00:00:00 2001 From: Tobias Richter Date: Fri, 6 Dec 2019 11:48:39 +0100 Subject: [PATCH 5/7] Moved heavy lifting of curl command line building to action plugin --- action_plugins/curl_cmdline_helper.py | 118 ++++++++++++++++++++++++++ tasks/curl.yml | 83 +++--------------- 2 files changed, 130 insertions(+), 71 deletions(-) create mode 100644 action_plugins/curl_cmdline_helper.py diff --git a/action_plugins/curl_cmdline_helper.py b/action_plugins/curl_cmdline_helper.py new file mode 100644 index 0000000..e716250 --- /dev/null +++ b/action_plugins/curl_cmdline_helper.py @@ -0,0 +1,118 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +from __future__ import (absolute_import, division, print_function) + +__metaclass__ = type + +import re + +from ansible.plugins.action import ActionBase +from ansible.template import Templar +from ansible.errors import AnsibleOptionsError + +try: + from __main__ import display +except ImportError: + from ansible.utils.display import Display + + display = Display() + + +class ActionModule(ActionBase): + TRANSFERS_FILES = False + + def __init__(self, task, connection, play_context, loader, templar, shared_loader_obj): + super(ActionModule, self).__init__(task, connection, play_context, loader, templar, shared_loader_obj) + self._task_vars = None + self._templar = templar + + def run(self, tmp=None, task_vars=None): + if task_vars is None: + task_vars = dict() + + result = super(ActionModule, self).run(tmp, task_vars) + + self._task_vars = task_vars + + try: + # Get config values + conga_aemdst_curl_url = self._get_arg_or_var('conga_aemdst_curl_url') + conga_aemdst_curl_expected_http_code = self._get_arg_or_var('conga_aemdst_curl_expected_http_code') + conga_aemdst_curl_follow_redirects_expected_http_code = self._get_arg_or_var('conga_aemdst_curl_follow_redirects_expected_http_code') + conga_aemdst_curl_follow_redirects = self._get_arg_or_var('conga_aemdst_curl_follow_redirects') + conga_aemdst_curl_allow_insecure = self._get_arg_or_var('conga_aemdst_curl_allow_insecure') + conga_aemdst_curl_noproxy = self._get_arg_or_var('conga_aemdst_curl_noproxy') + conga_aemdst_curl_resolve = self._get_arg_or_var('conga_aemdst_curl_resolve', [], False) + conga_aemdst_curl_headers = self._get_arg_or_var('conga_aemdst_curl_headers', [], False) + conga_aemdst_curl_timeout = self._get_arg_or_var('conga_aemdst_curl_timeout') + conga_aemdst_curl_connect_timeout = self._get_arg_or_var('conga_aemdst_curl_connect_timeout') + + except AnsibleOptionsError as err: + return self._fail_result(result, err.message) + + # set defaults + curl_cmdline_args = [ + '--max-time {}'.format(conga_aemdst_curl_timeout), + '--connect-timeout {}'.format(conga_aemdst_curl_connect_timeout), + ] + write_out_arg = "%{redirect_url}\n%{http_code}" + expected_http_code = conga_aemdst_curl_expected_http_code + + if conga_aemdst_curl_allow_insecure: + curl_cmdline_args.append('--insecure') + + for resolve in conga_aemdst_curl_resolve: + host = resolve.get("host") + port = resolve.get("port") + address = resolve.get("address") + curl_cmdline_args.append("--resolve '{}:{}:{}'".format(host, port, address)) + + if conga_aemdst_curl_follow_redirects: + curl_cmdline_args.append('--location') + write_out_arg = "%{url_effective}\n%{http_code}" + expected_http_code = conga_aemdst_curl_follow_redirects_expected_http_code + + if conga_aemdst_curl_noproxy: + curl_cmdline_args.append('--noproxy "*"') + + for header in conga_aemdst_curl_headers: + curl_cmdline_args.append('--header "{}"'.format(header)) + + curl_base_command = "curl {}".format(" ".join(curl_cmdline_args)) + curl_internal_command = '{} --write-out "{}" --output /dev/null --silent {}'.format(curl_base_command, + write_out_arg, + conga_aemdst_curl_url) + curl_debug_command = "{} {}".format(curl_base_command, conga_aemdst_curl_url) + + results = { + "curl_base_command": curl_base_command, + "curl_internal_command": curl_internal_command, + "curl_debug_command": curl_debug_command, + "expected_http_code": expected_http_code, + } + + result["ansible_facts"] = { + "conga_aemdst_curl_cmdline": results, + } + + # Always display resolved role and mapping + display.display( + "[[%s] => %s" % + (task_vars['inventory_hostname'], results)) + + return result + + @staticmethod + def _fail_result(result, message): + result['failed'] = True + result['msg'] = message + return result + + def _get_arg_or_var(self, name, default=None, is_required=True): + ret = self._task.args.get(name, self._task_vars.get(name, default)) + ret = self._templar.template(ret) + if is_required and ret is None: + raise AnsibleOptionsError("parameter %s is required" % name) + else: + return ret \ No newline at end of file diff --git a/tasks/curl.yml b/tasks/curl.yml index 15eddc9..7ab5d3c 100644 --- a/tasks/curl.yml +++ b/tasks/curl.yml @@ -8,84 +8,25 @@ msg: "Please define the url in variable: 'conga_aemdst_curl_expected_url'" when: conga_aemdst_curl_expected_url is none -- name: "Set default facts" - set_fact: - _write_out_arg: "%{redirect_url}\n%{http_code}" - _location_arg: "" - _insecure_arg: "" - _noproxy_arg: "" - _resolve_arg: "" - _headers_arg: "" - _expected_http_code: "{{ conga_aemdst_curl_expected_http_code }}" - -- name: "Set follow redirect facts" - set_fact: - _write_out_arg: "%{url_effective}\n%{http_code}" - _location_arg: "--location" - _expected_http_code: "{{ conga_aemdst_curl_follow_redirects_expected_http_code }}" - when: conga_aemdst_curl_follow_redirects - -- name: "Add '--insecure'" - set_fact: - _insecure_arg: "--insecure" - when: conga_aemdst_curl_allow_insecure - -- name: "Add '--noproxy'" - set_fact: - _noproxy_arg: '--noproxy "*"' - when: conga_aemdst_curl_noproxy +- name: "Build curl command line." + curl_cmdline_helper: -- name: "Add '--resolve'." - set_fact: - _resolve_arg: "{{ _resolve_arg }} --resolve '{{ item.host }}:{{ item.port }}:{{ item.address }}'" - with_items: - - "{{ conga_aemdst_curl_resolve }}" - when: conga_aemdst_curl_resolve is defined - -- name: "Add '--headers'." - set_fact: - _headers_arg: "{{ _headers_arg }} --header \"{{ item }}\"" - with_items: - - "{{ conga_aemdst_curl_headers }}" - when: conga_aemdst_curl_headers is defined - -- name: "Set base curl command." - set_fact: - _curl_base_command: >- - curl - {{ _insecure_arg }} - {{ _location_arg }} - {{ _noproxy_arg }} - {{ _resolve_arg }} - {{ _headers_arg }} - --max-time {{ conga_aemdst_curl_timeout }} - --connect-timeout {{ conga_aemdst_curl_connect_timeout }} - -- name: "{{ item }} : Set curl commands." - set_fact: - # command used internally only - _curl_internal_command: >- - {{ _curl_base_command }} - --write-out "{{ _write_out_arg }}" - --output /dev/null --silent - {{ conga_aemdst_curl_url }} - # command will be displayed to the user to ensure fast debugging - _curl_debug_command: >- - {{ _curl_base_command }} - {{ conga_aemdst_curl_url }} +- debug: + var: conga_aemdst_curl_cmdline + verbosity: 1 - debug: msg: - "check redirect from: {{ conga_aemdst_curl_url }}" - "check redirect to : {{ conga_aemdst_curl_expected_url }}" - - "check for http code: {{ _expected_http_code }}" + - "check for http code: {{ conga_aemdst_curl_cmdline.expected_http_code }}" - "Internal curl command:" - - "{{ _curl_internal_command }}" + - "{{ conga_aemdst_curl_cmdline.curl_internal_command }}" - "Debug curl command:" - - "{{ _curl_debug_command }}" + - "{{ conga_aemdst_curl_cmdline.curl_debug_command }}" - name: "Executing curl" - shell: "{{ _curl_internal_command }}" + shell: "{{ conga_aemdst_curl_cmdline.curl_internal_command }}" register: curl_result delegate_to: "{{ conga_aemdst_curl_host }}" args: @@ -121,11 +62,11 @@ actual : {{ _actual_url }} when: not conga_aemdst_curl_expected_url_test_lazy -- name: "Assert that actual response code matches {{ _expected_http_code }}" +- name: "Assert that actual response code matches {{ conga_aemdst_curl_cmdline.expected_http_code }}" assert: that: - - "{{ _expected_http_code }} == {{ _actual_http_code }}" + - "{{ conga_aemdst_curl_cmdline.expected_http_code }} == {{ _actual_http_code }}" msg: >- The actual http_code does not match with expected http_code - expected: {{ _expected_http_code }} + expected: {{ conga_aemdst_curl_cmdline.expected_http_code }} actual : {{ _actual_http_code }} From 7749749f2c3606860ed2d78c5af03ee58d6c85fa Mon Sep 17 00:00:00 2001 From: Tobias Richter Date: Fri, 6 Dec 2019 13:00:02 +0100 Subject: [PATCH 6/7] Fix resolve ip when server listen address is *, fix indent, remove display messages --- action_plugins/conga_aemdst_facts.py | 215 +++++++++++++------------- action_plugins/curl_cmdline_helper.py | 5 - 2 files changed, 108 insertions(+), 112 deletions(-) diff --git a/action_plugins/conga_aemdst_facts.py b/action_plugins/conga_aemdst_facts.py index 746eea7..9d9f597 100644 --- a/action_plugins/conga_aemdst_facts.py +++ b/action_plugins/conga_aemdst_facts.py @@ -13,115 +13,116 @@ from ansible.errors import AnsibleOptionsError try: - from __main__ import display + from __main__ import display except ImportError: - from ansible.utils.display import Display + from ansible.utils.display import Display - display = Display() + display = Display() class ActionModule(ActionBase): - TRANSFERS_FILES = False - - def __init__(self, task, connection, play_context, loader, templar, shared_loader_obj): - super(ActionModule, self).__init__(task, connection, play_context, loader, templar, shared_loader_obj) - self._task_vars = None - - def run(self, tmp=None, task_vars=None): - if task_vars is None: - task_vars = dict() - - result = super(ActionModule, self).run(tmp, task_vars) - - self._task_vars = task_vars - - try: - # Get conga_facts based config (whole or tenant config) - config = self._get_arg_or_var('conga_config') - - except AnsibleOptionsError as err: - return self._fail_result(result, err.message) - - httpd_cfg = config.get("httpd", {}) - ssl_cfg = httpd_cfg.get("ssl", {}) - ssl_enforce = ssl_cfg.get("enforce", False) - - ssl_offloading_cfg = ssl_cfg.get("offloading", {}) - ssl_offloading_enabled = ssl_offloading_cfg.get("enabled", False) - - # set defaults - server_listen_address = httpd_cfg.get("serverListenAddressSsl", "127.0.0.1") - server_listen_address_ssl = httpd_cfg.get("serverListenAddressSsl", "127.0.0.1") - - server_name = httpd_cfg.get("serverName", None) - server_name_ssl = httpd_cfg.get("serverNameSsl", None) - - listen_port = httpd_cfg.get("serverPort", 80) - listen_port_ssl = httpd_cfg.get("serverPortSsl", 443) - - initial_port = listen_port - expected_port = listen_port - - response_test_headers = [] - - # when ssl is enforced and not offloaded we are expecting the ssl port - if ssl_enforce and not ssl_offloading_enabled: - expected_port = listen_port_ssl - - listen_port_suffix = "" if listen_port == 80 else ":{}".format(initial_port) - listen_port_suffix_ssl = "" if listen_port_ssl == 443 else ":{}".format(expected_port) - - ssl_enforce_initial_url = "http://{}{}".format(server_name, listen_port_suffix) - ssl_enforce_expected_url = "https://{}{}/".format(server_name_ssl, listen_port_suffix_ssl) - - response_test_initial_url = ssl_enforce_initial_url - response_test_expected_url = response_test_initial_url + "/" - - if ssl_enforce: - if ssl_offloading_enabled: - # when ssl is offloaded we have to simulate a forwareded https request - response_test_headers.append("X-Forwarded-Proto: https") - else: - # when ssl is not offloaded we are expecting an ssl upgrade - response_test_expected_url = ssl_enforce_expected_url - - results = { - # "config": config, - "server_listen_address": server_listen_address, - "server_listen_address_ssl": server_listen_address_ssl, - "listen_port": listen_port, - "listen_port_ssl": listen_port_ssl, - "initial_port": initial_port, - "expected_port": expected_port, - "listen_port_suffix": listen_port_suffix, - "listen_port_suffix_ssl": listen_port_suffix_ssl, - "ssl_enforce_initial_url": ssl_enforce_initial_url, - "ssl_enforce_expected_url": ssl_enforce_expected_url, - "response_test_headers": response_test_headers, - "response_test_initial_url": response_test_initial_url, - "response_test_expected_url": response_test_expected_url - } - - result["ansible_facts"] = { - "conga_aemdst_config": results, - } - - # Always display resolved role and mapping - display.display( - "[[%s] => %s" % - (task_vars['inventory_hostname'], results)) - - return result - - @staticmethod - def _fail_result(result, message): - result['failed'] = True - result['msg'] = message - return result - - def _get_arg_or_var(self, name, default=None, is_required=True): - ret = self._task.args.get(name, self._task_vars.get(name, default)) - if is_required and not ret: - raise AnsibleOptionsError("parameter %s is required" % name) - else: - return ret + TRANSFERS_FILES = False + + def __init__(self, task, connection, play_context, loader, templar, shared_loader_obj): + super(ActionModule, self).__init__(task, connection, play_context, loader, templar, shared_loader_obj) + self._task_vars = None + + def run(self, tmp=None, task_vars=None): + if task_vars is None: + task_vars = dict() + + result = super(ActionModule, self).run(tmp, task_vars) + + self._task_vars = task_vars + + try: + # Get conga_facts based config (whole or tenant config) + config = self._get_arg_or_var('conga_config') + + except AnsibleOptionsError as err: + return self._fail_result(result, err.message) + + httpd_cfg = config.get("httpd", {}) + ssl_cfg = httpd_cfg.get("ssl", {}) + ssl_enforce = ssl_cfg.get("enforce", False) + + ssl_offloading_cfg = ssl_cfg.get("offloading", {}) + ssl_offloading_enabled = ssl_offloading_cfg.get("enabled", False) + + # set defaults + server_listen_address = httpd_cfg.get("serverListenAddressSsl", "127.0.0.1") + server_listen_address_ssl = httpd_cfg.get("serverListenAddressSsl", "127.0.0.1") + + if server_listen_address == "*": + server_listen_address = "127.0.0.1" + + if server_listen_address_ssl == "*": + server_listen_address_ssl = "127.0.0.1" + + server_name = httpd_cfg.get("serverName", None) + server_name_ssl = httpd_cfg.get("serverNameSsl", None) + + listen_port = httpd_cfg.get("serverPort", 80) + listen_port_ssl = httpd_cfg.get("serverPortSsl", 443) + + initial_port = listen_port + expected_port = listen_port + + response_test_headers = [] + + # when ssl is enforced and not offloaded we are expecting the ssl port + if ssl_enforce and not ssl_offloading_enabled: + expected_port = listen_port_ssl + + listen_port_suffix = "" if listen_port == 80 else ":{}".format(initial_port) + listen_port_suffix_ssl = "" if listen_port_ssl == 443 else ":{}".format(expected_port) + + ssl_enforce_initial_url = "http://{}{}".format(server_name, listen_port_suffix) + ssl_enforce_expected_url = "https://{}{}/".format(server_name_ssl, listen_port_suffix_ssl) + + response_test_initial_url = ssl_enforce_initial_url + response_test_expected_url = response_test_initial_url + "/" + + if ssl_enforce: + if ssl_offloading_enabled: + # when ssl is offloaded we have to simulate a forwareded https request + response_test_headers.append("X-Forwarded-Proto: https") + else: + # when ssl is not offloaded we are expecting an ssl upgrade + response_test_expected_url = ssl_enforce_expected_url + + results = { + # "config": config, + "server_listen_address": server_listen_address, + "server_listen_address_ssl": server_listen_address_ssl, + "listen_port": listen_port, + "listen_port_ssl": listen_port_ssl, + "initial_port": initial_port, + "expected_port": expected_port, + "listen_port_suffix": listen_port_suffix, + "listen_port_suffix_ssl": listen_port_suffix_ssl, + "ssl_enforce_initial_url": ssl_enforce_initial_url, + "ssl_enforce_expected_url": ssl_enforce_expected_url, + "response_test_headers": response_test_headers, + "response_test_initial_url": response_test_initial_url, + "response_test_expected_url": response_test_expected_url + } + + result["ansible_facts"] = { + "conga_aemdst_config": results, + } + + return result + + @staticmethod + def _fail_result(result, message): + result['failed'] = True + result['msg'] = message + return result + + def _get_arg_or_var(self, name, default=None, is_required=True): + ret = self._task.args.get(name, self._task_vars.get(name, default)) + if is_required and not ret: + raise AnsibleOptionsError("parameter %s is required" % name) + else: + return ret diff --git a/action_plugins/curl_cmdline_helper.py b/action_plugins/curl_cmdline_helper.py index e716250..90a58cf 100644 --- a/action_plugins/curl_cmdline_helper.py +++ b/action_plugins/curl_cmdline_helper.py @@ -96,11 +96,6 @@ def run(self, tmp=None, task_vars=None): "conga_aemdst_curl_cmdline": results, } - # Always display resolved role and mapping - display.display( - "[[%s] => %s" % - (task_vars['inventory_hostname'], results)) - return result @staticmethod From 1cfc83c5d36ac8cba6712164913fb298844d03bc Mon Sep 17 00:00:00 2001 From: Tobias Richter Date: Fri, 6 Dec 2019 14:02:46 +0100 Subject: [PATCH 7/7] Exclude custom action plugins from linting --- action_plugins/conga_aemdst_facts.py | 4 ---- action_plugins/curl_cmdline_helper.py | 3 --- tasks/curl.yml | 2 ++ tasks/response-test.yml | 2 ++ tasks/ssl-enforce-test.yml | 2 ++ 5 files changed, 6 insertions(+), 7 deletions(-) diff --git a/action_plugins/conga_aemdst_facts.py b/action_plugins/conga_aemdst_facts.py index 9d9f597..6d428fe 100644 --- a/action_plugins/conga_aemdst_facts.py +++ b/action_plugins/conga_aemdst_facts.py @@ -5,10 +5,6 @@ __metaclass__ = type -import os -import re - -from ansible.module_utils._text import to_native from ansible.plugins.action import ActionBase from ansible.errors import AnsibleOptionsError diff --git a/action_plugins/curl_cmdline_helper.py b/action_plugins/curl_cmdline_helper.py index 90a58cf..c1fcfb7 100644 --- a/action_plugins/curl_cmdline_helper.py +++ b/action_plugins/curl_cmdline_helper.py @@ -5,10 +5,7 @@ __metaclass__ = type -import re - from ansible.plugins.action import ActionBase -from ansible.template import Templar from ansible.errors import AnsibleOptionsError try: diff --git a/tasks/curl.yml b/tasks/curl.yml index 7ab5d3c..a099822 100644 --- a/tasks/curl.yml +++ b/tasks/curl.yml @@ -10,6 +10,8 @@ - name: "Build curl command line." curl_cmdline_helper: + tags: + - skip_ansible_lint - debug: var: conga_aemdst_curl_cmdline diff --git a/tasks/response-test.yml b/tasks/response-test.yml index 5467bb5..c337c17 100644 --- a/tasks/response-test.yml +++ b/tasks/response-test.yml @@ -1,6 +1,8 @@ - name: "Evaluate conga_aemdst_facts." conga_aemdst_facts: conga_config: "{{ response_test_config }}" + tags: + - skip_ansible_lint - name: "Output conga_aemdst_config." debug: diff --git a/tasks/ssl-enforce-test.yml b/tasks/ssl-enforce-test.yml index 78034bd..5eec208 100644 --- a/tasks/ssl-enforce-test.yml +++ b/tasks/ssl-enforce-test.yml @@ -1,6 +1,8 @@ - name: "Evaluate conga_aemdst_facts." conga_aemdst_facts: conga_config: "{{ enforce_ssl_config }}" + tags: + - skip_ansible_lint - name: "Output conga_aemdst_config." debug: