Skip to content

Commit ef7fa9f

Browse files
committed
Check user's permissions when expiring a silence
We implement a permission check logic at the Prometheus proxy API to ensure that users must have the Admin or Editor role on the service/project when they want to delete a silence for that service/project.
1 parent 860a101 commit ef7fa9f

File tree

1 file changed

+57
-0
lines changed

1 file changed

+57
-0
lines changed

promgen/proxy.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,63 @@ def post(self, request, *args, **kwargs):
344344
class ProxyDeleteSilence(View):
345345
def delete(self, request, silence_id):
346346
url = urljoin(util.setting("alertmanager:url"), f"/api/v2/silence/{silence_id}")
347+
# First, check if the silence exists
348+
response = util.get(url)
349+
if response.status_code != 200:
350+
return HttpResponse(
351+
response.text, status=response.status_code, content_type="application/json"
352+
)
353+
354+
# Check if the user has permission to delete the silence
355+
if not request.user.is_superuser:
356+
silence = response.json()
357+
project = None
358+
service = None
359+
for matcher in silence.get("matchers", []):
360+
if matcher.get("name") == "project":
361+
project = matcher.get("value")
362+
if matcher.get("name") == "service":
363+
service = matcher.get("value")
364+
if project is None and service is None:
365+
return JsonResponse(
366+
{
367+
"messages": [
368+
{
369+
"class": "alert alert-warning",
370+
"message": "Silence must have either a project or service matcher",
371+
}
372+
]
373+
},
374+
status=HTTPStatus.UNPROCESSABLE_ENTITY,
375+
)
376+
permission_denied_response = JsonResponse(
377+
{
378+
"messages": [
379+
{
380+
"class": "alert alert-danger",
381+
"message": "You do not have permission to delete this silence",
382+
}
383+
]
384+
},
385+
status=HTTPStatus.FORBIDDEN,
386+
)
387+
if project:
388+
project = models.Project.objects.get(name=project)
389+
if (
390+
not request.user.has_perm("project_admin", project)
391+
and not request.user.has_perm("project_editor", project)
392+
and not request.user.has_perm("service_admin", project.service)
393+
and not request.user.has_perm("service_editor", project.service)
394+
):
395+
return permission_denied_response
396+
elif service:
397+
service = models.Service.objects.get(name=service)
398+
if not request.user.has_perm(
399+
"service_admin", service
400+
) and not request.user.has_perm("service_editor", service):
401+
return permission_denied_response
402+
403+
# Delete the silence
347404
response = util.delete(url)
348405
return HttpResponse(
349406
response.text, status=response.status_code, content_type="application/json"

0 commit comments

Comments
 (0)