idealista / prom2teams

prom2teams is an HTTP server built with Python that receives alert notifications from a previously configured Prometheus Alertmanager instance and forwards it to Microsoft Teams using defined connectors
Apache License 2.0
270 stars 85 forks source link

[BUG] Change Office365 Webhook to Teams Workflow #350

Closed tassosgomes closed 3 weeks ago

tassosgomes commented 1 month ago

Description

Microsoft recently added the following message when using the Office365 Connector. "Action Required: O365 connectors within Teams will be deprecated and notifications from this service will stop. Learn more about the timing and how the Workflows app provides a more flexible and secure experience. If you want to continue receiving these types of messages, you can use a workflow to post messages from a webhook request. Set up workflow".

When following the recommended steps we started receiving the following error when trying to execute the post "configparser.InterpolationSyntaxError: '%' must be followed by '%' or '(', found: '%2Fmanual%%2Frun&sv=1.0&sig=mXASDASsaPihsdaARjeknv' "

Apparently there is an error in the webhook url that contains '%'

Steps to Reproduce

  1. Create Teams Power Automate Workflow and Select Webhook flow
  2. Copy Webhook Url and Update or Install Helm chart with Webhook Url's
  3. Send a Post request

Expected behavior: Send message to Teams Channel

Actual behavior: Error above

File "/usr/local/lib/python3.8/configparser.py", line 395, in before_get 2024-07-10T10:13:16.777425044-03:00 self._interpolate_some(parser, option, L, value, section, defaults, 1) 2024-07-10T10:13:16.777428260-03:00 File "/usr/local/lib/python3.8/configparser.py", line 442, in _interpolate_some 2024-07-10T10:13:16.777431522-03:00 raise InterpolationSyntaxError( 2024-07-10T10:13:16.777434864-03:00 configparser.InterpolationSyntaxError: '%' must be followed by '%' or '(', found:

Reproduces how often: 100% of time

Environment

simallaire commented 1 month ago

I have run into that error, tried escaping the '%' and now I have a status code 202 on the request

xtianae7 commented 1 month ago

We are currently investigating.

simallaire commented 1 month ago

I have run into that error, tried escaping the '%' and now I have a status code 202 on the request

Microsoft Power Automate web interface show me this error: The execution of template action 'Send_each_adaptive_card' failed: the result of the evaluation of 'foreach' expression '@triggerOutputs()?['body']?['attachments']' is of type 'Null'. The result must be a valid array.

toygame commented 1 month ago

Hi, I have some experience on Power Automate workflow.

You can decode the webhook URL from Workflow to string, not URI. I use the function "decodeURIComponent" in javascript to decode the URI

ex. Endpoint from Workflow: "https://xxx-56.southeastasia.logic.azure.com:443/workflows/asdfasdfdss/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=asdfasdf" Change to: "https://xxx-56.southeastasia.logic.azure.com:443/workflows/asdfasdfdss/triggers/manual/paths/invoke?api-version=2016-06-01&sp=/triggers/manual/run&sv=1.0&sig=asdfasdf"

and you must change the Adaptive card template like this { "type": "message", "attachments": [ { "contentType": "application/vnd.microsoft.card.adaptive", "content": { "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", "type": "AdaptiveCard", "version": "1.4", "msteams": { "width": "Full" }, "body": [ { "type": "ColumnSet", "style": "{% if status=='resolved' %} good {% else %} attention {% endif %}", "columns": [ { "type": "Column", "width": "stretch", "items": [ { "type": "TextBlock", "text": "Prometheus alert '{{ msg_text.name }}' {% if status=='resolved' %}(Resolved) {% elif status=='unknown' %} (status unknown) {% else %} triggered {% endif %}", "weight": "Bolder", "size": "Large" }, { "type": "TextBlock", "text": "{{ msg_text.summary }}", "wrap": true } ] } ] }, { "type": "FactSet", "facts": [ {% if msg_text.name %} { "title": "Alert", "value": "{{ msg_text.name }}" }, {% endif %} {% if msg_text.instance %} { "title": "In host", "value": "{{ msg_text.instance }}" }, {% endif %} {% if msg_text.severity %} { "title": "Severity", "value": "{{ msg_text.severity }}" }, {% endif %} {% if msg_text.description %} { "title": "Description", "value": "{{ msg_text.description }}" }, {% endif %} { "title": "Status", "value": "{{ msg_text.status }}" } {% if msg_text.extra_labels %} {% for key in msg_text.extra_labels %} , { "title": "{{ key }}", "value": "{{ msg_text.extra_labels[key] }}" } {% endfor %} {% endif %} {% if msg_text.extra_annotations %} {% for key in msg_text.extra_annotations %} , { "title": "{{ key }}", "value": "{{ msg_text.extra_annotations[key] }}" } {% endfor %} {% endif %} ] } ] } } ] }

FrankBlooBM commented 1 month ago

With the changes mentioned by @toygame the alerts seem to work again. However, your logs will still show errors because the new webhook URL seems to respond with an HTTP 202 which I think is not handled by the client.

angelosnm commented 1 month ago

FrankBlooBM

I confirm this behaviour...receiving 202 status code too upon changing the URL to the accepted format.

Traceback (most recent call last):
  File "/usr/local/lib/python3.8/site-packages/flask/app.py", line 2292, in wsgi_app
    response = self.full_dispatch_request()
  File "/usr/local/lib/python3.8/site-packages/flask/app.py", line 1815, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/usr/local/lib/python3.8/site-packages/flask_restplus/api.py", line 583, in error_router
    return original_handler(e)
  File "/usr/local/lib/python3.8/site-packages/flask_restplus/api.py", line 583, in error_router
    return original_handler(e)
  File "/usr/local/lib/python3.8/site-packages/flask/app.py", line 1718, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python3.8/site-packages/flask/_compat.py", line 35, in reraise
    raise value
  File "/usr/local/lib/python3.8/site-packages/flask/app.py", line 1813, in full_dispatch_request
    rv = self.dispatch_request()
  File "/usr/local/lib/python3.8/site-packages/flask/app.py", line 1799, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/usr/local/lib/python3.8/site-packages/flask_restplus/api.py", line 325, in wrapper
    resp = resource(*args, **kwargs)
  File "/usr/local/lib/python3.8/site-packages/flask/views.py", line 88, in view
    return self.dispatch_request(*args, **kwargs)
  File "/usr/local/lib/python3.8/site-packages/flask_restplus/resource.py", line 44, in dispatch_request
    resp = meth(*args, **kwargs)
  File "/usr/local/lib/python3.8/site-packages/prom2teams/app/versions/v2/namespace.py", line 27, in post
    self.sender.send_alerts(alerts, app.config['MICROSOFT_TEAMS'][connector])
  File "/usr/local/lib/python3.8/site-packages/prom2teams/app/sender.py", line 26, in send_alerts
    self.teams_client.post(teams_webhook_url, team_alert)
  File "/usr/local/lib/python3.8/site-packages/prom2teams/app/teams_client.py", line 43, in post
    simple_post(teams_webhook_url, message)
  File "/usr/local/lib/python3.8/site-packages/prom2teams/app/teams_client.py", line 37, in simple_post
    self._do_post(teams_webhook_url, message)
  File "/usr/local/lib/python3.8/site-packages/prom2teams/app/teams_client.py", line 56, in _do_post
    raise MicrosoftTeamsRequestException(
prom2teams.app.exceptions.MicrosoftTeamsRequestException: Error performing request to: https://prod-159.westeurope.logic.azure.com:443/workflows/86583a79c50e4463a53e2032887de3e1/triggers/manual/paths/invoke?api-version=2016-06-01&sp=/triggers/manual/run&sv=1.0&sig=BvEmy_LSZ6B1SXjlBDSY1aVn_O8Wa5uxvGKktSCNjhw.
 Returned status code: 202.
FrankBlooBM commented 1 month ago

I think it should be fairly safe to update the client to also accept 202 as a valid response. I'm more concerned about changing the template. I guess that updating the template to the new variant would break existing webhook calls, but I'm not too sure about that.

FrankBlooBM commented 1 month ago

I've been looking into updating the template and noticed that the impact is high. If my understanding is correct, the POST call that this project uses is on with a type MessageCard, as stated by Microsoft, this is now seen as legacy. Hence, moving to the new format of AdaptiveCards is a sensible idea.

The template from @toygame works also on the existing endpoints (tested with https://.webhook.office.com) so that would not be an issue. Hence I think it only takes some effort to convert the template & update all the tests. Not so sure what others think of this?

xtianae7 commented 4 weeks ago

Hello! We haven't had time to fix this yet. I personally tried the @toygame provided and it works like a charm. The main effort here looks like updating all the tests.

We will be looking into fixing this soon, but if you have something working already, feel free to contribute and open a PR :)

FrankBlooBM commented 4 weeks ago

@xtianae7 I've been able to make good progress, however, I face two issues: