Webhooks 2 hide secrets (#2104)
Replace password and authorization header fields with placeholders when returning data to the UI. Mask the authorization header field when editing and in the status logs.
This commit is contained in:
parent
889c0afab9
commit
bc535ac5df
5 changed files with 33 additions and 6 deletions
|
|
@ -4,6 +4,7 @@ from rest_framework import serializers
|
|||
from rest_framework.validators import UniqueTogetherValidator
|
||||
|
||||
from apps.webhooks.models import Webhook, WebhookResponse
|
||||
from apps.webhooks.models.webhook import WEBHOOK_FIELD_PLACEHOLDER
|
||||
from common.api_helpers.custom_fields import TeamPrimaryKeyRelatedField
|
||||
from common.api_helpers.utils import CurrentOrganizationDefault, CurrentTeamDefault, CurrentUserDefault
|
||||
from common.jinja_templater import apply_jinja_template
|
||||
|
|
@ -66,6 +67,21 @@ class WebhookSerializer(serializers.ModelSerializer):
|
|||
|
||||
validators = [UniqueTogetherValidator(queryset=Webhook.objects.all(), fields=["name", "organization"])]
|
||||
|
||||
def to_representation(self, instance):
|
||||
result = super().to_representation(instance)
|
||||
if instance.password:
|
||||
result["password"] = WEBHOOK_FIELD_PLACEHOLDER
|
||||
if instance.authorization_header:
|
||||
result["authorization_header"] = WEBHOOK_FIELD_PLACEHOLDER
|
||||
return result
|
||||
|
||||
def to_internal_value(self, data):
|
||||
if data.get("password") == WEBHOOK_FIELD_PLACEHOLDER:
|
||||
data["password"] = self.instance.password
|
||||
if data.get("authorization_header") == WEBHOOK_FIELD_PLACEHOLDER:
|
||||
data["authorization_header"] = self.instance.authorization_header
|
||||
return super().to_internal_value(data)
|
||||
|
||||
def _validate_template_field(self, template):
|
||||
try:
|
||||
apply_jinja_template(template, alert_payload=defaultdict(str), alert_group_id="alert_group_1")
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ from rest_framework.test import APIClient
|
|||
|
||||
from apps.api.permissions import LegacyAccessControlRole
|
||||
from apps.webhooks.models import Webhook
|
||||
from apps.webhooks.models.webhook import WEBHOOK_FIELD_PLACEHOLDER
|
||||
|
||||
TEST_URL = "https://some-url"
|
||||
|
||||
|
|
@ -44,8 +45,8 @@ def test_get_list_webhooks(webhook_internal_api_setup, make_user_auth_headers):
|
|||
"url": "https://github.com/",
|
||||
"data": '{"name": "{{ alert_payload }}"}',
|
||||
"username": "Chris Vanstras",
|
||||
"password": "qwerty",
|
||||
"authorization_header": "auth_token",
|
||||
"password": WEBHOOK_FIELD_PLACEHOLDER,
|
||||
"authorization_header": WEBHOOK_FIELD_PLACEHOLDER,
|
||||
"forward_all": False,
|
||||
"headers": None,
|
||||
"http_method": "POST",
|
||||
|
|
@ -85,8 +86,8 @@ def test_get_detail_webhook(webhook_internal_api_setup, make_user_auth_headers):
|
|||
"url": "https://github.com/",
|
||||
"data": '{"name": "{{ alert_payload }}"}',
|
||||
"username": "Chris Vanstras",
|
||||
"password": "qwerty",
|
||||
"authorization_header": "auth_token",
|
||||
"password": WEBHOOK_FIELD_PLACEHOLDER,
|
||||
"authorization_header": WEBHOOK_FIELD_PLACEHOLDER,
|
||||
"forward_all": False,
|
||||
"headers": None,
|
||||
"http_method": "POST",
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ from common.jinja_templater import apply_jinja_template
|
|||
from common.jinja_templater.apply_jinja_template import JinjaTemplateError, JinjaTemplateWarning
|
||||
from common.public_primary_keys import generate_public_primary_key, increase_public_primary_key_length
|
||||
|
||||
WEBHOOK_FIELD_PLACEHOLDER = "****************"
|
||||
|
||||
|
||||
def generate_public_primary_key_for_webhook():
|
||||
prefix = "WH"
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ from apps.alerts.models import AlertGroup, AlertGroupLogRecord, EscalationPolicy
|
|||
from apps.base.models import UserNotificationPolicyLogRecord
|
||||
from apps.user_management.models import User
|
||||
from apps.webhooks.models import Webhook, WebhookResponse
|
||||
from apps.webhooks.models.webhook import WEBHOOK_FIELD_PLACEHOLDER
|
||||
from apps.webhooks.utils import (
|
||||
InvalidWebhookData,
|
||||
InvalidWebhookHeaders,
|
||||
|
|
@ -94,6 +95,12 @@ def _build_payload(webhook, alert_group, user):
|
|||
return data
|
||||
|
||||
|
||||
def mask_authorization_header(headers):
|
||||
if "Authorization" in headers:
|
||||
headers["Authorization"] = WEBHOOK_FIELD_PLACEHOLDER
|
||||
return headers
|
||||
|
||||
|
||||
def make_request(webhook, alert_group, data):
|
||||
status = {
|
||||
"url": None,
|
||||
|
|
@ -115,7 +122,8 @@ def make_request(webhook, alert_group, data):
|
|||
if triggered:
|
||||
status["url"] = webhook.build_url(data)
|
||||
request_kwargs = webhook.build_request_kwargs(data, raise_data_errors=True)
|
||||
status["request_headers"] = json.dumps(request_kwargs.get("headers", {}))
|
||||
headers = mask_authorization_header(request_kwargs.get("headers", {}))
|
||||
status["request_headers"] = json.dumps(headers)
|
||||
if "json" in request_kwargs:
|
||||
status["request_data"] = json.dumps(request_kwargs["json"])
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ export const form: { name: string; fields: FormItem[] } = {
|
|||
},
|
||||
{
|
||||
name: 'authorization_header',
|
||||
type: FormItemType.Input,
|
||||
type: FormItemType.Password,
|
||||
},
|
||||
{
|
||||
name: 'trigger_template',
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue