policies: add policy log messages to test endpoints

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
Jens Langhammer 2022-04-01 22:07:35 +02:00
parent 4be238018b
commit d84ff2bbca
18 changed files with 2065 additions and 2302 deletions

View File

@ -17,6 +17,7 @@ from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet from rest_framework.viewsets import ModelViewSet
from rest_framework_guardian.filters import ObjectPermissionsFilter from rest_framework_guardian.filters import ObjectPermissionsFilter
from structlog.stdlib import get_logger from structlog.stdlib import get_logger
from structlog.testing import capture_logs
from authentik.admin.api.metrics import CoordinateSerializer from authentik.admin.api.metrics import CoordinateSerializer
from authentik.api.decorators import permission_required from authentik.api.decorators import permission_required
@ -132,13 +133,22 @@ class ApplicationViewSet(UsedByMixin, ModelViewSet):
return HttpResponseBadRequest("for_user must be numerical") return HttpResponseBadRequest("for_user must be numerical")
engine = PolicyEngine(application, for_user, request) engine = PolicyEngine(application, for_user, request)
engine.use_cache = False engine.use_cache = False
with capture_logs() as logs:
engine.build() engine.build()
result = engine.result result = engine.result
response = PolicyTestResultSerializer(PolicyResult(False)) response = PolicyTestResultSerializer(PolicyResult(False))
if result.passing: if result.passing:
response = PolicyTestResultSerializer(PolicyResult(True)) response = PolicyTestResultSerializer(PolicyResult(True))
if request.user.is_superuser: if request.user.is_superuser:
log_messages = []
for log in logs:
if log.get("process", "") == "PolicyProcess":
continue
log_messages.append(log)
result.log_messages = log_messages
response = PolicyTestResultSerializer(result) response = PolicyTestResultSerializer(result)
# print(response.log_messages)
print(response.data)
return Response(response.data) return Response(response.data)
@extend_schema( @extend_schema(

View File

@ -1,5 +1,5 @@
"""Serializer for policy execution""" """Serializer for policy execution"""
from rest_framework.fields import BooleanField, CharField, JSONField, ListField from rest_framework.fields import BooleanField, CharField, DictField, JSONField, ListField
from rest_framework.relations import PrimaryKeyRelatedField from rest_framework.relations import PrimaryKeyRelatedField
from authentik.core.api.utils import PassiveSerializer, is_dict from authentik.core.api.utils import PassiveSerializer, is_dict
@ -18,3 +18,4 @@ class PolicyTestResultSerializer(PassiveSerializer):
passing = BooleanField() passing = BooleanField()
messages = ListField(child=CharField(), read_only=True) messages = ListField(child=CharField(), read_only=True)
log_messages = ListField(child=DictField(), read_only=True)

View File

@ -11,6 +11,7 @@ from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer, SerializerMethodField from rest_framework.serializers import ModelSerializer, SerializerMethodField
from rest_framework.viewsets import GenericViewSet from rest_framework.viewsets import GenericViewSet
from structlog.stdlib import get_logger from structlog.stdlib import get_logger
from structlog.testing import capture_logs
from authentik.api.decorators import permission_required from authentik.api.decorators import permission_required
from authentik.core.api.applications import user_app_cache_key from authentik.core.api.applications import user_app_cache_key
@ -166,6 +167,13 @@ class PolicyViewSet(
p_request.context = test_params.validated_data.get("context", {}) p_request.context = test_params.validated_data.get("context", {})
proc = PolicyProcess(PolicyBinding(policy=policy), p_request, None) proc = PolicyProcess(PolicyBinding(policy=policy), p_request, None)
with capture_logs() as logs:
result = proc.execute() result = proc.execute()
log_messages = []
for log in logs:
if log.get("process", "") == "PolicyProcess":
continue
log_messages.append(log)
result.log_messages = log_messages
response = PolicyTestResultSerializer(result) response = PolicyTestResultSerializer(result)
return Response(response.data) return Response(response.data)

View File

@ -90,6 +90,7 @@ class PolicyProcess(PROCESS_CLASS):
"P_ENG(proc): Running policy", "P_ENG(proc): Running policy",
policy=self.binding.policy, policy=self.binding.policy,
user=self.request.user, user=self.request.user,
# this is used for filtering in access checking where logs are sent to the admin
process="PolicyProcess", process="PolicyProcess",
) )
try: try:
@ -121,6 +122,7 @@ class PolicyProcess(PROCESS_CLASS):
"P_ENG(proc): finished and cached ", "P_ENG(proc): finished and cached ",
policy=self.binding.policy, policy=self.binding.policy,
result=policy_result, result=policy_result,
# this is used for filtering in access checking where logs are sent to the admin
process="PolicyProcess", process="PolicyProcess",
passing=policy_result.passing, passing=policy_result.passing,
user=self.request.user, user=self.request.user,

View File

@ -67,6 +67,8 @@ class PolicyResult:
source_binding: Optional["PolicyBinding"] source_binding: Optional["PolicyBinding"]
source_results: Optional[list["PolicyResult"]] source_results: Optional[list["PolicyResult"]]
log_messages: Optional[list[dict]]
def __init__(self, passing: bool, *messages: str): def __init__(self, passing: bool, *messages: str):
super().__init__() super().__init__()
self.passing = passing self.passing = passing

View File

@ -28761,7 +28761,14 @@ components:
items: items:
type: string type: string
readOnly: true readOnly: true
log_messages:
type: array
items:
type: object
additionalProperties: {}
readOnly: true
required: required:
- log_messages
- messages - messages
- passing - passing
Prompt: Prompt:

View File

@ -2811,6 +2811,11 @@ msgstr "Lokal"
#~ msgid "Locale" #~ msgid "Locale"
#~ msgstr "Gebietsschema" #~ msgstr "Gebietsschema"
#: src/pages/applications/ApplicationCheckAccessForm.ts
#: src/pages/policies/PolicyTestForm.ts
msgid "Log messages"
msgstr ""
#: src/pages/stages/user_login/UserLoginStageForm.ts #: src/pages/stages/user_login/UserLoginStageForm.ts
msgid "Log the currently pending user in." msgid "Log the currently pending user in."
msgstr "Melden Sie den aktuell ausstehenden Benutzer an." msgstr "Melden Sie den aktuell ausstehenden Benutzer an."
@ -3172,6 +3177,11 @@ msgstr "Kein Formular gefunden"
msgid "No integration active" msgid "No integration active"
msgstr "Keine Integrationen aktiv" msgstr "Keine Integrationen aktiv"
#: src/pages/applications/ApplicationCheckAccessForm.ts
#: src/pages/policies/PolicyTestForm.ts
msgid "No log messages."
msgstr ""
#: src/elements/events/ObjectChangelog.ts #: src/elements/events/ObjectChangelog.ts
#: src/elements/events/UserEvents.ts #: src/elements/events/UserEvents.ts
msgid "No matching events could be found." msgid "No matching events could be found."

View File

@ -2855,6 +2855,11 @@ msgstr "Local"
#~ msgid "Locale" #~ msgid "Locale"
#~ msgstr "Locale" #~ msgstr "Locale"
#: src/pages/applications/ApplicationCheckAccessForm.ts
#: src/pages/policies/PolicyTestForm.ts
msgid "Log messages"
msgstr "Log messages"
#: src/pages/stages/user_login/UserLoginStageForm.ts #: src/pages/stages/user_login/UserLoginStageForm.ts
msgid "Log the currently pending user in." msgid "Log the currently pending user in."
msgstr "Log the currently pending user in." msgstr "Log the currently pending user in."
@ -3217,6 +3222,11 @@ msgstr "No form found"
msgid "No integration active" msgid "No integration active"
msgstr "No integration active" msgstr "No integration active"
#: src/pages/applications/ApplicationCheckAccessForm.ts
#: src/pages/policies/PolicyTestForm.ts
msgid "No log messages."
msgstr "No log messages."
#: src/elements/events/ObjectChangelog.ts #: src/elements/events/ObjectChangelog.ts
#: src/elements/events/UserEvents.ts #: src/elements/events/UserEvents.ts
msgid "No matching events could be found." msgid "No matching events could be found."

View File

@ -2804,6 +2804,11 @@ msgstr "Local"
#~ msgid "Locale" #~ msgid "Locale"
#~ msgstr "Lugar" #~ msgstr "Lugar"
#: src/pages/applications/ApplicationCheckAccessForm.ts
#: src/pages/policies/PolicyTestForm.ts
msgid "Log messages"
msgstr ""
#: src/pages/stages/user_login/UserLoginStageForm.ts #: src/pages/stages/user_login/UserLoginStageForm.ts
msgid "Log the currently pending user in." msgid "Log the currently pending user in."
msgstr "Registra al usuario pendiente en ese momento." msgstr "Registra al usuario pendiente en ese momento."
@ -3165,6 +3170,11 @@ msgstr "No se encontró ningún formulario"
msgid "No integration active" msgid "No integration active"
msgstr "Sin integración activa" msgstr "Sin integración activa"
#: src/pages/applications/ApplicationCheckAccessForm.ts
#: src/pages/policies/PolicyTestForm.ts
msgid "No log messages."
msgstr ""
#: src/elements/events/ObjectChangelog.ts #: src/elements/events/ObjectChangelog.ts
#: src/elements/events/UserEvents.ts #: src/elements/events/UserEvents.ts
msgid "No matching events could be found." msgid "No matching events could be found."

View File

@ -2835,6 +2835,11 @@ msgstr "Local"
#~ msgid "Locale" #~ msgid "Locale"
#~ msgstr "" #~ msgstr ""
#: src/pages/applications/ApplicationCheckAccessForm.ts
#: src/pages/policies/PolicyTestForm.ts
msgid "Log messages"
msgstr ""
#: src/pages/stages/user_login/UserLoginStageForm.ts #: src/pages/stages/user_login/UserLoginStageForm.ts
msgid "Log the currently pending user in." msgid "Log the currently pending user in."
msgstr "Ouvre la session de l'utilisateur courant." msgstr "Ouvre la session de l'utilisateur courant."
@ -3196,6 +3201,11 @@ msgstr "Aucun formulaire trouvé"
msgid "No integration active" msgid "No integration active"
msgstr "Aucune intégration active" msgstr "Aucune intégration active"
#: src/pages/applications/ApplicationCheckAccessForm.ts
#: src/pages/policies/PolicyTestForm.ts
msgid "No log messages."
msgstr ""
#: src/elements/events/ObjectChangelog.ts #: src/elements/events/ObjectChangelog.ts
#: src/elements/events/UserEvents.ts #: src/elements/events/UserEvents.ts
msgid "No matching events could be found." msgid "No matching events could be found."

View File

@ -2801,6 +2801,11 @@ msgstr "Lokalny"
#~ msgid "Locale" #~ msgid "Locale"
#~ msgstr "Język" #~ msgstr "Język"
#: src/pages/applications/ApplicationCheckAccessForm.ts
#: src/pages/policies/PolicyTestForm.ts
msgid "Log messages"
msgstr ""
#: src/pages/stages/user_login/UserLoginStageForm.ts #: src/pages/stages/user_login/UserLoginStageForm.ts
msgid "Log the currently pending user in." msgid "Log the currently pending user in."
msgstr "Loguj aktualnie oczekującego użytkownika." msgstr "Loguj aktualnie oczekującego użytkownika."
@ -3162,6 +3167,11 @@ msgstr "Nie znaleziono formularza"
msgid "No integration active" msgid "No integration active"
msgstr "Brak aktywnej integracji" msgstr "Brak aktywnej integracji"
#: src/pages/applications/ApplicationCheckAccessForm.ts
#: src/pages/policies/PolicyTestForm.ts
msgid "No log messages."
msgstr ""
#: src/elements/events/ObjectChangelog.ts #: src/elements/events/ObjectChangelog.ts
#: src/elements/events/UserEvents.ts #: src/elements/events/UserEvents.ts
msgid "No matching events could be found." msgid "No matching events could be found."

View File

@ -2845,6 +2845,11 @@ msgstr ""
#~ msgid "Locale" #~ msgid "Locale"
#~ msgstr "" #~ msgstr ""
#: src/pages/applications/ApplicationCheckAccessForm.ts
#: src/pages/policies/PolicyTestForm.ts
msgid "Log messages"
msgstr ""
#: src/pages/stages/user_login/UserLoginStageForm.ts #: src/pages/stages/user_login/UserLoginStageForm.ts
msgid "Log the currently pending user in." msgid "Log the currently pending user in."
msgstr "" msgstr ""
@ -3207,6 +3212,11 @@ msgstr ""
msgid "No integration active" msgid "No integration active"
msgstr "" msgstr ""
#: src/pages/applications/ApplicationCheckAccessForm.ts
#: src/pages/policies/PolicyTestForm.ts
msgid "No log messages."
msgstr ""
#: src/elements/events/ObjectChangelog.ts #: src/elements/events/ObjectChangelog.ts
#: src/elements/events/UserEvents.ts #: src/elements/events/UserEvents.ts
msgid "No matching events could be found." msgid "No matching events could be found."

View File

@ -2805,6 +2805,11 @@ msgstr "Yerel"
#~ msgid "Locale" #~ msgid "Locale"
#~ msgstr "Yerelleştirme" #~ msgstr "Yerelleştirme"
#: src/pages/applications/ApplicationCheckAccessForm.ts
#: src/pages/policies/PolicyTestForm.ts
msgid "Log messages"
msgstr ""
#: src/pages/stages/user_login/UserLoginStageForm.ts #: src/pages/stages/user_login/UserLoginStageForm.ts
msgid "Log the currently pending user in." msgid "Log the currently pending user in."
msgstr "Şu anda bekleyen kullanıcıya oturum açın." msgstr "Şu anda bekleyen kullanıcıya oturum açın."
@ -3166,6 +3171,11 @@ msgstr "Form bulunamadı"
msgid "No integration active" msgid "No integration active"
msgstr "Entegrasyon etkin" msgstr "Entegrasyon etkin"
#: src/pages/applications/ApplicationCheckAccessForm.ts
#: src/pages/policies/PolicyTestForm.ts
msgid "No log messages."
msgstr ""
#: src/elements/events/ObjectChangelog.ts #: src/elements/events/ObjectChangelog.ts
#: src/elements/events/UserEvents.ts #: src/elements/events/UserEvents.ts
msgid "No matching events could be found." msgid "No matching events could be found."

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,11 @@
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { TemplateResult, html } from "lit"; import { CSSResult, TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
import { until } from "lit/directives/until.js"; import { until } from "lit/directives/until.js";
import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList/description-list.css";
import { Application, CoreApi, PolicyTestResult } from "@goauthentik/api"; import { Application, CoreApi, PolicyTestResult } from "@goauthentik/api";
import { DEFAULT_CONFIG } from "../../api/Config"; import { DEFAULT_CONFIG } from "../../api/Config";
@ -42,8 +44,13 @@ export class ApplicationCheckAccessForm extends Form<{ forUser: number }> {
this.result = undefined; this.result = undefined;
} }
static get styles(): CSSResult[] {
return super.styles.concat(PFDescriptionList);
}
renderResult(): TemplateResult { renderResult(): TemplateResult {
return html` <ak-form-element-horizontal label=${t`Passing`}> return html`
<ak-form-element-horizontal label=${t`Passing`}>
<div class="pf-c-form__group-label"> <div class="pf-c-form__group-label">
<div class="c-form__horizontal-group"> <div class="c-form__horizontal-group">
<span class="pf-c-form__label-text"> <span class="pf-c-form__label-text">
@ -70,7 +77,38 @@ export class ApplicationCheckAccessForm extends Form<{ forUser: number }> {
</ul> </ul>
</div> </div>
</div> </div>
</ak-form-element-horizontal>`; </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Log messages`}>
<div class="pf-c-form__group-label">
<div class="c-form__horizontal-group">
<dl class="pf-c-description-list pf-m-horizontal">
${(this.result?.logMessages || []).length > 0
? this.result?.logMessages?.map((m) => {
return html`<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text"
>${m.log_level}</span
>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
${m.event}
</div>
</dd>
</div>`;
})
: html`<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text"
>${t`No log messages.`}</span
>
</dt>
</div>`}
</dl>
</div>
</div>
</ak-form-element-horizontal>
`;
} }
renderForm(): TemplateResult { renderForm(): TemplateResult {

View File

@ -2,10 +2,12 @@ import YAML from "yaml";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { TemplateResult, html } from "lit"; import { CSSResult, TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
import { until } from "lit/directives/until.js"; import { until } from "lit/directives/until.js";
import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList/description-list.css";
import { import {
CoreApi, CoreApi,
PoliciesApi, PoliciesApi,
@ -47,8 +49,13 @@ export class PolicyTestForm extends Form<PolicyTestRequest> {
.then((result) => (this.result = result)); .then((result) => (this.result = result));
}; };
static get styles(): CSSResult[] {
return super.styles.concat(PFDescriptionList);
}
renderResult(): TemplateResult { renderResult(): TemplateResult {
return html` <ak-form-element-horizontal label=${t`Passing`}> return html`
<ak-form-element-horizontal label=${t`Passing`}>
<div class="pf-c-form__group-label"> <div class="pf-c-form__group-label">
<div class="c-form__horizontal-group"> <div class="c-form__horizontal-group">
<span class="pf-c-form__label-text"> <span class="pf-c-form__label-text">
@ -75,7 +82,39 @@ export class PolicyTestForm extends Form<PolicyTestRequest> {
</ul> </ul>
</div> </div>
</div> </div>
</ak-form-element-horizontal>`; </ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Log messages`}>
<div class="pf-c-form__group-label">
<div class="c-form__horizontal-group">
<dl class="pf-c-description-list pf-m-horizontal">
${(this.result?.logMessages || []).length > 0
? this.result?.logMessages?.map((m) => {
return html`<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text"
>${m.log_level}</span
>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
${m.event}
</div>
</dd>
</div>`;
})
: html`<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text"
>${t`No log messages.`}</span
>
</dt>
</div>`}
</dl>
</div>
</div>
</ak-form-element-horizontal>
`;
} }
renderForm(): TemplateResult { renderForm(): TemplateResult {