Skip to content

Commit 2f85b1f

Browse files
msteams: Support Power Automate Workflows via Adaptive Card format (#13082)
* msteams: Use adaptive cards format * update docs * revert webhook scan_added_empty
1 parent 5329068 commit 2f85b1f

22 files changed

Lines changed: 1212 additions & 579 deletions
67 KB
Loading

docs/content/en/customize_dojo/notifications/email_slack_teams.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ If you want to apply RBAC\-based filtering to your Slack messages, enabling pers
9999

100100
If your team has a Slack integration enabled (through the above process), individual users can also configure notifications to send directly to your personal Slackbot channel.
101101

102-
1. Start by navigating to your personal Profile page on DefectDojo. Find this by clicking the 👤 **icon** in the top\-right corner. Select your DefectDojo Username from the list. (👤 **paul** in our example)
102+
1. Start by navigating to your personal Profile page on DefectDojo. Find this by clicking the 👤 **icon** in the top\-right corner. Select your DefectDojo Username from the list. (👤 **paul** in our example)
103103
104104
![image](images/Configure_a_Slack_Integration_4.png)
105105

@@ -111,14 +111,16 @@ You can now [set specific notifications](../about_notifications/) to be sent to
111111

112112
Microsoft Teams can receive notifications to a specific channel. To do this, you will need to **set up an incoming webhook** on the channel where you wish to receive messages.
113113

114-
1. Complete the process listed in the **[Microsoft Teams Documentation](https://learn.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook?tabs=dotnet)** for creating a new Incoming Webhook. Keep your unique webhook.office.com link handy as you will need it in subsequent steps.
114+
Please note that the old [Office Connector webhooks](https://learn.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook?tabs=newteams%2Cdotnet) will be retired by Microsoft, use a new Power Automate Workflow based webhook as documented below.
115+
116+
1. Complete the process listed in the **[Microsoft Teams Documentation](https://support.microsoft.com/en-us/office/create-incoming-webhooks-with-workflows-for-microsoft-teams-8ae491c7-0394-4861-ba59-055e33f75498)** for creating a new Incoming Webhook. Keep your unique logic.azure.com link handy as you will need it in subsequent steps. You can create webhook for a channel or for a specific chat.
115117
116118
![image](images/Configure_a_Microsoft_Teams_Integration.png)
117119
2. In DefectDojo, navigate to **Configuration \> System Settings** from the sidebar. (In the Pro UI, this form is located under **Enterprise Settings > System Settings**.)
118-
3. Check the **Enable Microsoft Teams notifications** box. This will open a hidden section of the form, labeled **‘Msteams url**’.
120+
3. Check the **Enable Microsoft Teams notifications** box. This will open a hidden section of the form, labeled **‘Msteams url**’.
119121
120122
![image](images/Configure_a_Microsoft_Teams_Integration_2.png)
121-
4. Paste the webhook.office.com URL (created in Step 1\) in the **Msteams url** box. Your Teams app will now listen to incoming Notifications from DefectDojo and post them to the channel you selected.
123+
4. Paste the logic.azure.com URL (created in Step 1\) in the **Msteams url** box. Your Teams app will now listen to incoming Notifications from DefectDojo and post them to the channel you selected.
122124

123125
### Notes on the Teams integration
124126

dojo/notifications/helper.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,9 +335,10 @@ def send_msteams_notification(
335335
"msteams",
336336
kwargs,
337337
),
338+
headers={"Content-Type": "application/json"},
338339
timeout=settings.REQUESTS_TIMEOUT,
339340
)
340-
if res.status_code != 200:
341+
if not (200 <= res.status_code < 300):
341342
logger.error("Error when sending message to Microsoft Teams")
342343
logger.error(res.status_code)
343344
logger.error(res.text)

dojo/templates/notifications/alert/report_created.tpl

Lines changed: 0 additions & 3 deletions
This file was deleted.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
scan_added.tpl
1+
{% include "notifications/alert/scan_added.tpl" %}

dojo/templates/notifications/mail/report_created.tpl

Lines changed: 0 additions & 37 deletions
This file was deleted.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
scan_added.tpl
1+
{% include "notifications/mail/scan_added.tpl" %}
Lines changed: 98 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,103 @@
1-
{% load i18n %}
2-
{% load display_tags %}
1+
{% load i18n %}{% load display_tags %}{% url 'view_engagement' engagement.id as url %}
32
{
4-
"@context": "https://schema.org/extensions",
5-
"@type": "MessageCard",
6-
"title": "{% trans "Engagement added" %}",
7-
"summary": "{% trans "Engagement added" %}",
8-
"sections": [
3+
"type": "message",
4+
"attachments": [
95
{
10-
"activityTitle": "DefectDojo",
11-
"activityImage": "https://raw.githubusercontent.com/DefectDojo/django-DefectDojo/master/dojo/static/dojo/img/chop.png",
12-
"text": "{% trans "A new engagement has been added" %}.",
13-
"facts": [
14-
{
15-
"name": "{% trans "Product" %}:",
16-
"value": "{{ engagement.product.name }}"
17-
},
18-
{
19-
"name": "{% trans "Engagement" %}:",
20-
"value": "{{ engagement.name }}"
21-
}
22-
]
23-
}
24-
{% if system_settings.disclaimer_notifications and system_settings.disclaimer_notifications.strip %}
25-
,{
26-
"activityTitle": "{% trans "Disclaimer" %}",
27-
"text": "{{ system_settings.disclaimer_notifications }}"
6+
"contentType": "application/vnd.microsoft.card.adaptive",
7+
"content": {
8+
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
9+
"type": "AdaptiveCard",
10+
"version": "1.4",
11+
"body": [
12+
{
13+
"type": "ColumnSet",
14+
"columns": [
15+
{
16+
"type": "Column",
17+
"width": "auto",
18+
"items": [
19+
{
20+
"type": "Image",
21+
"url": "https://raw.githubusercontent.com/DefectDojo/django-DefectDojo/master/dojo/static/dojo/img/chop.png",
22+
"size": "Small"
23+
}
24+
]
25+
},
26+
{
27+
"type": "Column",
28+
"width": "stretch",
29+
"items": [
30+
{
31+
"type": "TextBlock",
32+
"text": "DefectDojo",
33+
"weight": "Bolder",
34+
"size": "Medium"
35+
},
36+
{
37+
"type": "TextBlock",
38+
"text": "{% trans 'Engagement Added' %}",
39+
"weight": "Bolder",
40+
"size": "Large",
41+
"color": "Accent"
42+
}
43+
]
44+
}
45+
]
46+
},
47+
{
48+
"type": "TextBlock",
49+
"text": "{% trans 'A new engagement' %} [{{ engagement.name }}]({{ url|full_url }}) {% trans 'has been added.' %}",
50+
"wrap": true,
51+
"spacing": "Medium"
52+
},
53+
{
54+
"type": "FactSet",
55+
"facts": [
56+
{
57+
"title": "{% trans 'Product' %}:",
58+
"value": "{{ engagement.product.name }}"
59+
},
60+
{
61+
"title": "{% trans 'Engagement' %}:",
62+
"value": "{{ engagement.name }}"
63+
},
64+
{
65+
"title": "{% trans 'Start date' %}:",
66+
"value": "{{ engagement.target_start }}"
67+
},
68+
{
69+
"title": "{% trans 'End date' %}:",
70+
"value": "{{ engagement.target_end }}"
71+
}
72+
],
73+
"spacing": "Medium"
74+
}{% if system_settings.disclaimer_notifications and system_settings.disclaimer_notifications.strip %},
75+
{
76+
"type": "Container",
77+
"style": "attention",
78+
"items": [
79+
{
80+
"type": "TextBlock",
81+
"text": "{% trans 'Disclaimer' %}",
82+
"weight": "Bolder"
83+
},
84+
{
85+
"type": "TextBlock",
86+
"text": "{{ system_settings.disclaimer_notifications }}",
87+
"wrap": true
88+
}
89+
],
90+
"spacing": "Medium"
91+
}{% endif %}
92+
],
93+
"actions": [
94+
{
95+
"type": "Action.OpenUrl",
96+
"title": "{% trans 'View Engagement' %}",
97+
"url": "{{ url|full_url }}"
98+
}
99+
]
28100
}
29-
{% endif %}
30-
31-
],
32-
"potentialAction": [
33-
{
34-
"@type": "OpenUri",
35-
"name": "{% trans "View Engagement" %}",
36-
"targets": [
37-
{
38-
"os": "default",
39-
"uri": "{{ url|full_url }}"
40-
}
41-
]
42101
}
43102
]
44-
}
103+
}
Lines changed: 97 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,103 @@
1-
{% load i18n %}
2-
{% load display_tags %}
1+
{% load i18n %}{% load display_tags %}{% url 'view_engagement' engagement.id as url %}
32
{
4-
"@context": "https://schema.org/extensions",
5-
"@type": "MessageCard",
6-
"title": "{% trans "Engagement closed" %}",
7-
"summary": "{% trans "Engagement closed" %}",
8-
"sections": [
3+
"type": "message",
4+
"attachments": [
95
{
10-
"activityTitle": "DefectDojo",
11-
"activityImage": "https://raw.githubusercontent.com/DefectDojo/django-DefectDojo/master/dojo/static/dojo/img/chop.png",
12-
"text": "{% trans "An engagement has been closed" %}.",
13-
"facts": [
14-
{
15-
"name": "{% trans "Product" %}:",
16-
"value": "{{ engagement.product.name }}"
17-
},
18-
{
19-
"name": "{% trans "Engagement" %}:",
20-
"value": "{{ engagement.name }}"
21-
}
22-
]
23-
}
24-
{% if system_settings.disclaimer and system_settings.disclaimer.strip %}
25-
,{
26-
"activityTitle": "{% trans "Disclaimer" %}",
27-
"text": "{{ system_settings.disclaimer }}"
6+
"contentType": "application/vnd.microsoft.card.adaptive",
7+
"content": {
8+
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
9+
"type": "AdaptiveCard",
10+
"version": "1.4",
11+
"body": [
12+
{
13+
"type": "ColumnSet",
14+
"columns": [
15+
{
16+
"type": "Column",
17+
"width": "auto",
18+
"items": [
19+
{
20+
"type": "Image",
21+
"url": "https://raw.githubusercontent.com/DefectDojo/django-DefectDojo/master/dojo/static/dojo/img/chop.png",
22+
"size": "Small"
23+
}
24+
]
25+
},
26+
{
27+
"type": "Column",
28+
"width": "stretch",
29+
"items": [
30+
{
31+
"type": "TextBlock",
32+
"text": "DefectDojo",
33+
"weight": "Bolder",
34+
"size": "Medium"
35+
},
36+
{
37+
"type": "TextBlock",
38+
"text": "{% trans 'Engagement Closed' %}",
39+
"weight": "Bolder",
40+
"size": "Large",
41+
"color": "Accent"
42+
}
43+
]
44+
}
45+
]
46+
},
47+
{
48+
"type": "TextBlock",
49+
"text": "{% trans 'An engagement' %} [{{ engagement.name }}]({{ url|full_url }}) {% trans 'has been closed.' %}",
50+
"wrap": true,
51+
"spacing": "Medium"
52+
},
53+
{
54+
"type": "FactSet",
55+
"facts": [
56+
{
57+
"title": "{% trans 'Product' %}:",
58+
"value": "{{ engagement.product.name }}"
59+
},
60+
{
61+
"title": "{% trans 'Engagement' %}:",
62+
"value": "{{ engagement.name }}"
63+
},
64+
{
65+
"title": "{% trans 'Start date' %}:",
66+
"value": "{{ engagement.target_start }}"
67+
},
68+
{
69+
"title": "{% trans 'End date' %}:",
70+
"value": "{{ engagement.target_end }}"
71+
}
72+
],
73+
"spacing": "Medium"
74+
}{% if system_settings.disclaimer_notifications and system_settings.disclaimer_notifications.strip %},
75+
{
76+
"type": "Container",
77+
"style": "attention",
78+
"items": [
79+
{
80+
"type": "TextBlock",
81+
"text": "{% trans 'Disclaimer' %}",
82+
"weight": "Bolder"
83+
},
84+
{
85+
"type": "TextBlock",
86+
"text": "{{ system_settings.disclaimer_notifications }}",
87+
"wrap": true
88+
}
89+
],
90+
"spacing": "Medium"
91+
}{% endif %}
92+
],
93+
"actions": [
94+
{
95+
"type": "Action.OpenUrl",
96+
"title": "{% trans 'View Engagement' %}",
97+
"url": "{{ url|full_url }}"
98+
}
99+
]
28100
}
29-
{% endif %}
30-
31-
],
32-
"potentialAction": [
33-
{
34-
"@type": "OpenUri",
35-
"name": "{% trans "View Engagement" %}",
36-
"targets": [
37-
{
38-
"os": "default",
39-
"uri": "{{ url|full_url }}"
40-
}
41-
]
42101
}
43102
]
44103
}

0 commit comments

Comments
 (0)