diff --git a/awx/main/tests/unit/api/test_logger.py b/awx/main/tests/unit/api/test_logger.py index 7ff9a39b02..b15636b42a 100644 --- a/awx/main/tests/unit/api/test_logger.py +++ b/awx/main/tests/unit/api/test_logger.py @@ -158,3 +158,17 @@ def test_rsyslog_conf_template(enabled, type, host, port, protocol, expected_con # check validity of created template assert expected_config in tmpl + + +def test_splunk_auth(): + mock_settings, _ = _mock_logging_defaults() + # Set test settings + logging_defaults = getattr(settings, 'LOGGING') + setattr(mock_settings, 'LOGGING', logging_defaults) + setattr(mock_settings, 'LOG_AGGREGATOR_ENABLED', True) + setattr(mock_settings, 'LOG_AGGREGATOR_TYPE', 'splunk') + setattr(mock_settings, 'LOG_AGGREGATOR_HOST', 'example.org') + setattr(mock_settings, 'LOG_AGGREGATOR_PASSWORD', 'SECRET-TOKEN') + + tmpl = construct_rsyslog_conf_template(mock_settings) + assert 'httpheaderkey="Authorization" httpheadervalue="Splunk SECRET-TOKEN"' in tmpl diff --git a/awx/main/utils/external_logging.py b/awx/main/utils/external_logging.py index f3d747b300..dad788e45f 100644 --- a/awx/main/utils/external_logging.py +++ b/awx/main/utils/external_logging.py @@ -60,11 +60,21 @@ def construct_rsyslog_conf_template(settings=settings): params.append(f'restpath="{path}"') username = getattr(settings, 'LOG_AGGREGATOR_USERNAME', '') password = getattr(settings, 'LOG_AGGREGATOR_PASSWORD', '') - if username: + if getattr(settings, 'LOG_AGGREGATOR_TYPE', None) == 'splunk': + # splunk has a weird authorization header + if password: + # from omhttp docs: + # https://www.rsyslog.com/doc/v8-stable/configuration/modules/omhttp.html + # > Currently only a single additional header/key pair is + # > configurable, further development is needed to support + # > arbitrary header key/value lists. + params.append('httpheaderkey="Authorization"') + params.append(f'httpheadervalue="Splunk {password}"') + elif username: params.append(f'uid="{username}"') - if username and password: - # you can only have a basic auth password if there's a username - params.append(f'pwd="{password}"') + if password: + # you can only have a basic auth password if there's a username + params.append(f'pwd="{password}"') params = ' '.join(params) parts.extend(['module(load="omhttp")', f'action({params})']) elif protocol and host and port: diff --git a/awx/main/utils/formatters.py b/awx/main/utils/formatters.py index 8e3ddabf1b..61666f83b0 100644 --- a/awx/main/utils/formatters.py +++ b/awx/main/utils/formatters.py @@ -244,4 +244,7 @@ class LogstashFormatter(LogstashFormatterBase): if record.exc_info: message.update(self.get_debug_fields(record)) + if settings.LOG_AGGREGATOR_TYPE == 'splunk': + # splunk messages must have a top level "event" key + message = {'event': message} return self.serialize(message)