policies/reputation: fix reputation not expiring (#6714)

* policies/reputation: fix reputation not expiring

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix some verbose names for models

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Jens L 2023-08-31 13:46:00 +02:00 committed by GitHub
parent 6163f29aa0
commit f57b3efcaa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 101 additions and 24 deletions

View file

@ -26,4 +26,11 @@ class Migration(migrations.Migration):
fields=["key"], name="authentik_e_key_523e13_hash"
),
),
migrations.AlterModelOptions(
name="licenseusage",
options={
"verbose_name": "License Usage",
"verbose_name_plural": "License Usage Records",
},
),
]

View file

@ -15,6 +15,7 @@ from django.contrib.postgres.indexes import HashIndex
from django.db import models
from django.db.models.query import QuerySet
from django.utils.timezone import now
from django.utils.translation import gettext as _
from guardian.shortcuts import get_anonymous_user
from jwt import PyJWTError, decode, get_unverified_header
from rest_framework.exceptions import ValidationError
@ -187,3 +188,7 @@ class LicenseUsage(ExpiringModel):
within_limits = models.BooleanField()
record_date = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = _("License Usage")
verbose_name_plural = _("License Usage Records")

View file

@ -84,6 +84,9 @@ ldap:
tls:
ciphers: null
reputation:
expiry: 86400
cookie_domain: null
disable_update_check: false
disable_startup_analytics: false

View file

@ -0,0 +1,33 @@
# Generated by Django 4.2.4 on 2023-08-31 10:42
from django.db import migrations, models
import authentik.policies.reputation.models
class Migration(migrations.Migration):
dependencies = [
("authentik_policies_reputation", "0004_reputationpolicy_authentik_p_policy__8f0d70_idx"),
]
operations = [
migrations.AddField(
model_name="reputation",
name="expires",
field=models.DateTimeField(
default=authentik.policies.reputation.models.reputation_expiry
),
),
migrations.AddField(
model_name="reputation",
name="expiring",
field=models.BooleanField(default=True),
),
migrations.AlterModelOptions(
name="reputation",
options={
"verbose_name": "Reputation Score",
"verbose_name_plural": "Reputation Scores",
},
),
]

View file

@ -1,13 +1,17 @@
"""authentik reputation request policy"""
from datetime import timedelta
from uuid import uuid4
from django.db import models
from django.db.models import Sum
from django.db.models.query_utils import Q
from django.utils.timezone import now
from django.utils.translation import gettext as _
from rest_framework.serializers import BaseSerializer
from structlog import get_logger
from authentik.core.models import ExpiringModel
from authentik.lib.config import CONFIG
from authentik.lib.models import SerializerModel
from authentik.lib.utils.http import get_client_ip
from authentik.policies.models import Policy
@ -17,6 +21,11 @@ LOGGER = get_logger()
CACHE_KEY_PREFIX = "goauthentik.io/policies/reputation/scores/"
def reputation_expiry():
"""Reputation expiry"""
return now() + timedelta(seconds=CONFIG.get_int("reputation.expiry"))
class ReputationPolicy(Policy):
"""Return true if request IP/target username's score is below a certain threshold"""
@ -59,7 +68,7 @@ class ReputationPolicy(Policy):
verbose_name_plural = _("Reputation Policies")
class Reputation(SerializerModel):
class Reputation(ExpiringModel, SerializerModel):
"""Reputation for user and or IP."""
reputation_uuid = models.UUIDField(primary_key=True, unique=True, default=uuid4)
@ -69,6 +78,8 @@ class Reputation(SerializerModel):
ip_geo_data = models.JSONField(default=dict)
score = models.BigIntegerField(default=0)
expires = models.DateTimeField(default=reputation_expiry)
updated = models.DateTimeField(auto_now_add=True)
@property
@ -81,4 +92,6 @@ class Reputation(SerializerModel):
return f"Reputation {self.identifier}/{self.ip} @ {self.score}"
class Meta:
verbose_name = _("Reputation Score")
verbose_name_plural = _("Reputation Scores")
unique_together = ("identifier", "ip")

View file

@ -30,7 +30,7 @@ def check_plex_token(self: MonitoredTask, source_slug: int):
self.set_status(TaskResult(TaskResultStatus.SUCCESSFUL, ["Plex token is valid."]))
except RequestException as exc:
error = exception_to_string(exc)
if len(source.plex_token) < 1:
if len(source.plex_token) > 0:
error = error.replace(source.plex_token, "$PLEX_TOKEN")
self.set_status(
TaskResult(

View file

@ -12961,7 +12961,7 @@ paths:
schema:
type: string
format: uuid
description: A UUID string identifying this reputation.
description: A UUID string identifying this Reputation Score.
required: true
tags:
- policies
@ -12995,7 +12995,7 @@ paths:
schema:
type: string
format: uuid
description: A UUID string identifying this reputation.
description: A UUID string identifying this Reputation Score.
required: true
tags:
- policies
@ -13026,7 +13026,7 @@ paths:
schema:
type: string
format: uuid
description: A UUID string identifying this reputation.
description: A UUID string identifying this Reputation Score.
required: true
tags:
- policies
@ -29523,7 +29523,7 @@ components:
* `authentik_policies_expression.expressionpolicy` - Expression Policy
* `authentik_policies_password.passwordpolicy` - Password Policy
* `authentik_policies_reputation.reputationpolicy` - Reputation Policy
* `authentik_policies_reputation.reputation` - reputation
* `authentik_policies_reputation.reputation` - Reputation Score
* `authentik_policies.policybinding` - Policy Binding
* `authentik_providers_ldap.ldapprovider` - LDAP Provider
* `authentik_providers_oauth2.scopemapping` - Scope Mapping
@ -29713,7 +29713,7 @@ components:
* `authentik_policies_expression.expressionpolicy` - Expression Policy
* `authentik_policies_password.passwordpolicy` - Password Policy
* `authentik_policies_reputation.reputationpolicy` - Reputation Policy
* `authentik_policies_reputation.reputation` - reputation
* `authentik_policies_reputation.reputation` - Reputation Score
* `authentik_policies.policybinding` - Policy Binding
* `authentik_providers_ldap.ldapprovider` - LDAP Provider
* `authentik_providers_oauth2.scopemapping` - Scope Mapping
@ -31943,7 +31943,7 @@ components:
* `authentik_policies_expression.expressionpolicy` - Expression Policy
* `authentik_policies_password.passwordpolicy` - Password Policy
* `authentik_policies_reputation.reputationpolicy` - Reputation Policy
* `authentik_policies_reputation.reputation` - reputation
* `authentik_policies_reputation.reputation` - Reputation Score
* `authentik_policies.policybinding` - Policy Binding
* `authentik_providers_ldap.ldapprovider` - LDAP Provider
* `authentik_providers_oauth2.scopemapping` - Scope Mapping
@ -34930,7 +34930,7 @@ components:
* `authentik_policies_expression.expressionpolicy` - Expression Policy
* `authentik_policies_password.passwordpolicy` - Password Policy
* `authentik_policies_reputation.reputationpolicy` - Reputation Policy
* `authentik_policies_reputation.reputation` - reputation
* `authentik_policies_reputation.reputation` - Reputation Score
* `authentik_policies.policybinding` - Policy Binding
* `authentik_providers_ldap.ldapprovider` - LDAP Provider
* `authentik_providers_oauth2.scopemapping` - Scope Mapping

View file

@ -258,16 +258,18 @@ new?labels=bug,from_authentik&title=${encodeURIComponent(title)}
return html` <div class="pf-c-card__title">${msg("Secret:")}</div>
${this.getModelInfo(this.event.context.secret as EventModel)}`;
case EventActions.SystemException:
return html` <a
class="pf-c-button pf-m-primary"
target="_blank"
href=${this.buildGitHubIssueUrl(this.event.context)}
>
${msg("Open issue on GitHub...")}
</a>
<div class="pf-l-flex">
return html`<div class="pf-l-flex">
<div class="pf-l-flex__item">
<div class="pf-c-card__title">${msg("Exception")}</div>
<div class="pf-c-card__title">
<a
class="pf-c-button pf-m-primary"
target="_blank"
href=${this.buildGitHubIssueUrl(this.event.context)}
>
${msg("Open issue on GitHub...")}
</a>
</div>
<div class="pf-c-card__body">
<pre>${this.event.context.message}</pre>
</div>

View file

@ -51,15 +51,19 @@ kubectl exec -it deployment/authentik-worker -c authentik -- ak dump_config
- `AUTHENTIK_REDIS__CACHE_TIMEOUT_POLICIES`: Timeout for cached policies until they expire in seconds, defaults to 300
- `AUTHENTIK_REDIS__CACHE_TIMEOUT_REPUTATION`: Timeout for cached reputation until they expire in seconds, defaults to 300
:::info
`AUTHENTIK_REDIS__CACHE_TIMEOUT_REPUTATION` only applies to the cache expiry, see [`AUTHENTIK_REPUTATION__EXPIRY`](#authentik_reputation__expiry) to control how long reputation is persisted for.
:::
## Listen Setting
- `AUTHENTIK_LISTEN__HTTP`: Listening address:port (e.g. `0.0.0.0:9000`) for HTTP (Server and Proxy outpost)
- `AUTHENTIK_LISTEN__HTTPS`: Listening address:port (e.g. `0.0.0.0:9443`) for HTTPS (Server and Proxy outpost)
- `AUTHENTIK_LISTEN__LDAP`: Listening address:port (e.g. `0.0.0.0:3389`) for LDAP (LDAP outpost)
- `AUTHENTIK_LISTEN__LDAPS`: Listening address:port (e.g. `0.0.0.0:6636`) for LDAPS (LDAP outpost)
- `AUTHENTIK_LISTEN__METRICS`: Listening address:port (e.g. `0.0.0.0:9300`) for Prometheus metrics (All)
- `AUTHENTIK_LISTEN__DEBUG`: Listening address:port (e.g. `0.0.0.0:9900`) for Go Debugging metrics (All)
- `AUTHENTIK_LISTEN__TRUSTED_PROXY_CIDRS`: List of CIDRs that proxy headers should be accepted from (Server)
- `AUTHENTIK_LISTEN__HTTP`: Listening address:port (e.g. `0.0.0.0:9000`) for HTTP (Applies to Server and Proxy outpost)
- `AUTHENTIK_LISTEN__HTTPS`: Listening address:port (e.g. `0.0.0.0:9443`) for HTTPS (Applies to Server and Proxy outpost)
- `AUTHENTIK_LISTEN__LDAP`: Listening address:port (e.g. `0.0.0.0:3389`) for LDAP (Applies to LDAP outpost)
- `AUTHENTIK_LISTEN__LDAPS`: Listening address:port (e.g. `0.0.0.0:6636`) for LDAPS (Applies to LDAP outpost)
- `AUTHENTIK_LISTEN__METRICS`: Listening address:port (e.g. `0.0.0.0:9300`) for Prometheus metrics (Applies to All)
- `AUTHENTIK_LISTEN__DEBUG`: Listening address:port (e.g. `0.0.0.0:9900`) for Go Debugging metrics (Applies to All)
- `AUTHENTIK_LISTEN__TRUSTED_PROXY_CIDRS`: List of CIDRs that proxy headers should be accepted from (Applies to Server)
Defaults to `127.0.0.0/8`, `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`, `fe80::/10`, `::1/128`.
@ -297,6 +301,16 @@ Allows configuration of TLS Cliphers for LDAP connections used by LDAP sources.
Defaults to `null`.
### `AUTHENTIK_REPUTATION__EXPIRY`
:::info
Requires authentik 2023.8.2
:::
Configure how long reputation scores should be saved for in seconds. Note that this is different than [`AUTHENTIK_REDIS__CACHE_TIMEOUT_REPUTATION`](#redis-settings), as reputation is saved to the database every 5 minutes.
Defaults to `86400`.
### `AUTHENTIK_WEB__WORKERS`
:::info