sensu / sensu-email-handler

Sensu Go Email Handler Plugin
https://sensu.io
MIT License
11 stars 17 forks source link

Email handler is not able to format nested HTML output #60

Open raihanchdy opened 3 years ago

raihanchdy commented 3 years ago

I am using email handler plugin and installed using below command.

sensuctl asset add sensu/sensu-email-handler -r email-handler

below is the check definition { “api_version”:“core/v2”, “type”:“Check”, “metadata”:{ “namespace”:“default”, “name”:“app-gw-health-check”, “labels”:{} }, “spec”:{ “command”:“python3.6 /etc/sensu/plugins/app-gw-health-check.py”, “subscriptions”:[ “roundrobin:worker” ], “publish”:true, “round_robin”:true, “interval”:3600, “handlers”:[ “alert_handler”, “resolve_handler” ], “proxy_entity_name”:“proxyclient”, “timeout”:590 } }

Output is not getting formatted while loading using {{.Check.Output}}

image

image

I have updated on sensu go forum as well. https://discourse.sensu.io/t/html-output-for-mail-body-is-rendering-in-webui/2308/3

nixwiz commented 3 years ago

This handler will only format the message as html if the template it uses has the tag in it. Per this section of the code.

Can you please post a copy of your template (as a code block) here for review?

raihanchdy commented 3 years ago

If you look at the below output, email handler is already formatting the template.

image

the marked one on the above screenshot is not getting formatted.

Script output is not getting formatted when loads using {{.Check.Output}} inside the template.

Please find the template

Check Name {{ .Check.Name }}
Check Status CRITICAL
Check Output {{ .Check.Output }}
Timestamp {{(UnixTime .Check.Executed)}}

In the above template if I paste the script output in place of {{.Check.Output}} then it works as expected. Only issue when it tries to load the output into the template.

nixwiz commented 3 years ago

Okay, I've found where this is happening. When using an HTML template we are using the html/template package to expand the tokens. When it expands {{ .Check.Output }} which, in your case, contains HTML, it escapes it, producing the following:

<html>
<style type="text/css">
.tg  {border-collapse:collapse;border-spacing:0;}
.tg td{font-family:Arial, sans-serif;font-size:13px;padding:7px 5px;border-style:solid;border-width:1px;overflow:hidden;word-
break:normal;border-color:black;}
.tg th{font-family:Arial, sans-serif;font-size:13px;font-weight:normal;padding:7px 5px;border-style:solid;border-
width:1px;overflow:hidden;word-break:normal;border-color:black;}
.tg .tg-ydru{font-family:Arial, Geneva, sans-serif !important;;background-color:#efefef;border-color:#9b9b9b;vertical-align:top}
.tg .tg-greenbg{font-family:Arial, Geneva, sans-serif !important;;background-color:#a4ff48;border-color:#9b9b9b;vertical-
align:top}
.tg .tg-amberbg{font-family:Arial, Geneva, sans-serif !important;;background-color:#e5b73b;border-color:#9b9b9b;vertical-
align:top}
.tg .tg-redbg{font-family:Arial, Geneva, sans-serif !important;;background-color: #ff6347;border-color:#9b9b9b;vertical-
align:top}
.tg .tg-rb8b{background-color:#efefef;border-color:#9b9b9b;vertical-align:top}
.verinfo {color:Gray;font-family:Arial, sans-serif;font-size:9px}
</style>

<body>

 <table class="tg">
    <tr>
        <td class="tg-ydru">Check Name</td>
        <td class="tg-ydru">{{ .Check.Name }}</td>
    </tr>
    <tr>
        <td class="tg-ydru">Check Status</td>
        <td class="tg-redbg">CRITICAL</td>
    </tr>
    <tr>
        <td class="tg-ydru">Check Output</td>
    <td class="tg-ydru">&lt;table class=&#34;tg&#34;&gt;&lt;tr&gt;&lt;th&gt;#&lt;/th&gt; &lt;th&gt;Instance Name&lt;/th&gt; &lt;th&gt;Status&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;engg-az-dev1-utilset1-ss_-1&lt;/td&gt;&lt;td&gt;Unhealthy&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;table class=&#34;tg&#34;&gt;&lt;tr&gt;&lt;th&gt;#&lt;/th&gt; &lt;th&gt;Instance Name&lt;/th&gt; &lt;th&gt;Status&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;engg-az-dev1-utilset1-ss_-0&lt;/td&gt;&lt;td&gt;Unhealthy&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</td>
    </tr>
    <tr>
        <td class="tg-ydru">Timestamp</td>
        <td class="tg-ydru">{{(UnixTime .Check.Executed)}}</td>
    </tr>
</table>

</body>
</html>

@echlebek any thoughts on this? We want to continue the use of html/template to sanitize the html, but anything we can do to keep it from escaping a token containing html?

raihanchdy commented 3 years ago

The HTML output indented to be parsed by the handler template but same output appears on Web UI

image

I believe the web UI should parse the html output and show formatted values. The same works very well in sensu core with uchiwa.

echlebek commented 3 years ago

I'm not sure it's possible to do this without creating a security vulnerability.

For some users, that might be acceptable, if they control the system to the extent that they're sure they will never get malicious HTML. But I don't think we can make that decision for everyone. The Web UI can't be allowed to display arbitrary HTML in general.

@nixwiz I believe we could support this use case in the email handler by allowing check output to be a template itself. The Go template engine supports nesting templates, so we could add a feature flag that would allow the check output to be parsed as a template and included that way.

rehanch178 commented 3 years ago

@echlebek , would be great if you can add the flag to load the check output as a template.

raihanchdy commented 3 years ago

@nixwiz @echlebek , Any update on the additional flag for the events output. Would be great if you can let me know when the next release is coming with the fix of output template.

raihanchdy commented 3 years ago

@nixwiz @echlebek , I modified the source code of email handler where I replaced \u0026lt; by \u003c and \u0026gt; by \u003e in the msg body . The handler is giving desired output

image

echlebek commented 3 years ago

@raihanchdy we are still discussing what, if any, action would be correct to take. It's not clear that adding complexity here would be beneficial.