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:
parent
6163f29aa0
commit
f57b3efcaa
|
@ -26,4 +26,11 @@ class Migration(migrations.Migration):
|
||||||
fields=["key"], name="authentik_e_key_523e13_hash"
|
fields=["key"], name="authentik_e_key_523e13_hash"
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name="licenseusage",
|
||||||
|
options={
|
||||||
|
"verbose_name": "License Usage",
|
||||||
|
"verbose_name_plural": "License Usage Records",
|
||||||
|
},
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -15,6 +15,7 @@ from django.contrib.postgres.indexes import HashIndex
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models.query import QuerySet
|
from django.db.models.query import QuerySet
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
|
from django.utils.translation import gettext as _
|
||||||
from guardian.shortcuts import get_anonymous_user
|
from guardian.shortcuts import get_anonymous_user
|
||||||
from jwt import PyJWTError, decode, get_unverified_header
|
from jwt import PyJWTError, decode, get_unverified_header
|
||||||
from rest_framework.exceptions import ValidationError
|
from rest_framework.exceptions import ValidationError
|
||||||
|
@ -187,3 +188,7 @@ class LicenseUsage(ExpiringModel):
|
||||||
within_limits = models.BooleanField()
|
within_limits = models.BooleanField()
|
||||||
|
|
||||||
record_date = models.DateTimeField(auto_now_add=True)
|
record_date = models.DateTimeField(auto_now_add=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = _("License Usage")
|
||||||
|
verbose_name_plural = _("License Usage Records")
|
||||||
|
|
|
@ -84,6 +84,9 @@ ldap:
|
||||||
tls:
|
tls:
|
||||||
ciphers: null
|
ciphers: null
|
||||||
|
|
||||||
|
reputation:
|
||||||
|
expiry: 86400
|
||||||
|
|
||||||
cookie_domain: null
|
cookie_domain: null
|
||||||
disable_update_check: false
|
disable_update_check: false
|
||||||
disable_startup_analytics: false
|
disable_startup_analytics: false
|
||||||
|
|
|
@ -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",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
|
@ -1,13 +1,17 @@
|
||||||
"""authentik reputation request policy"""
|
"""authentik reputation request policy"""
|
||||||
|
from datetime import timedelta
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models import Sum
|
from django.db.models import Sum
|
||||||
from django.db.models.query_utils import Q
|
from django.db.models.query_utils import Q
|
||||||
|
from django.utils.timezone import now
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
from rest_framework.serializers import BaseSerializer
|
from rest_framework.serializers import BaseSerializer
|
||||||
from structlog import get_logger
|
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.models import SerializerModel
|
||||||
from authentik.lib.utils.http import get_client_ip
|
from authentik.lib.utils.http import get_client_ip
|
||||||
from authentik.policies.models import Policy
|
from authentik.policies.models import Policy
|
||||||
|
@ -17,6 +21,11 @@ LOGGER = get_logger()
|
||||||
CACHE_KEY_PREFIX = "goauthentik.io/policies/reputation/scores/"
|
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):
|
class ReputationPolicy(Policy):
|
||||||
"""Return true if request IP/target username's score is below a certain threshold"""
|
"""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")
|
verbose_name_plural = _("Reputation Policies")
|
||||||
|
|
||||||
|
|
||||||
class Reputation(SerializerModel):
|
class Reputation(ExpiringModel, SerializerModel):
|
||||||
"""Reputation for user and or IP."""
|
"""Reputation for user and or IP."""
|
||||||
|
|
||||||
reputation_uuid = models.UUIDField(primary_key=True, unique=True, default=uuid4)
|
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)
|
ip_geo_data = models.JSONField(default=dict)
|
||||||
score = models.BigIntegerField(default=0)
|
score = models.BigIntegerField(default=0)
|
||||||
|
|
||||||
|
expires = models.DateTimeField(default=reputation_expiry)
|
||||||
|
|
||||||
updated = models.DateTimeField(auto_now_add=True)
|
updated = models.DateTimeField(auto_now_add=True)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -81,4 +92,6 @@ class Reputation(SerializerModel):
|
||||||
return f"Reputation {self.identifier}/{self.ip} @ {self.score}"
|
return f"Reputation {self.identifier}/{self.ip} @ {self.score}"
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
verbose_name = _("Reputation Score")
|
||||||
|
verbose_name_plural = _("Reputation Scores")
|
||||||
unique_together = ("identifier", "ip")
|
unique_together = ("identifier", "ip")
|
||||||
|
|
|
@ -30,7 +30,7 @@ def check_plex_token(self: MonitoredTask, source_slug: int):
|
||||||
self.set_status(TaskResult(TaskResultStatus.SUCCESSFUL, ["Plex token is valid."]))
|
self.set_status(TaskResult(TaskResultStatus.SUCCESSFUL, ["Plex token is valid."]))
|
||||||
except RequestException as exc:
|
except RequestException as exc:
|
||||||
error = exception_to_string(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")
|
error = error.replace(source.plex_token, "$PLEX_TOKEN")
|
||||||
self.set_status(
|
self.set_status(
|
||||||
TaskResult(
|
TaskResult(
|
||||||
|
|
14
schema.yml
14
schema.yml
|
@ -12961,7 +12961,7 @@ paths:
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
format: uuid
|
format: uuid
|
||||||
description: A UUID string identifying this reputation.
|
description: A UUID string identifying this Reputation Score.
|
||||||
required: true
|
required: true
|
||||||
tags:
|
tags:
|
||||||
- policies
|
- policies
|
||||||
|
@ -12995,7 +12995,7 @@ paths:
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
format: uuid
|
format: uuid
|
||||||
description: A UUID string identifying this reputation.
|
description: A UUID string identifying this Reputation Score.
|
||||||
required: true
|
required: true
|
||||||
tags:
|
tags:
|
||||||
- policies
|
- policies
|
||||||
|
@ -13026,7 +13026,7 @@ paths:
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
format: uuid
|
format: uuid
|
||||||
description: A UUID string identifying this reputation.
|
description: A UUID string identifying this Reputation Score.
|
||||||
required: true
|
required: true
|
||||||
tags:
|
tags:
|
||||||
- policies
|
- policies
|
||||||
|
@ -29523,7 +29523,7 @@ components:
|
||||||
* `authentik_policies_expression.expressionpolicy` - Expression Policy
|
* `authentik_policies_expression.expressionpolicy` - Expression Policy
|
||||||
* `authentik_policies_password.passwordpolicy` - Password Policy
|
* `authentik_policies_password.passwordpolicy` - Password Policy
|
||||||
* `authentik_policies_reputation.reputationpolicy` - Reputation Policy
|
* `authentik_policies_reputation.reputationpolicy` - Reputation Policy
|
||||||
* `authentik_policies_reputation.reputation` - reputation
|
* `authentik_policies_reputation.reputation` - Reputation Score
|
||||||
* `authentik_policies.policybinding` - Policy Binding
|
* `authentik_policies.policybinding` - Policy Binding
|
||||||
* `authentik_providers_ldap.ldapprovider` - LDAP Provider
|
* `authentik_providers_ldap.ldapprovider` - LDAP Provider
|
||||||
* `authentik_providers_oauth2.scopemapping` - Scope Mapping
|
* `authentik_providers_oauth2.scopemapping` - Scope Mapping
|
||||||
|
@ -29713,7 +29713,7 @@ components:
|
||||||
* `authentik_policies_expression.expressionpolicy` - Expression Policy
|
* `authentik_policies_expression.expressionpolicy` - Expression Policy
|
||||||
* `authentik_policies_password.passwordpolicy` - Password Policy
|
* `authentik_policies_password.passwordpolicy` - Password Policy
|
||||||
* `authentik_policies_reputation.reputationpolicy` - Reputation Policy
|
* `authentik_policies_reputation.reputationpolicy` - Reputation Policy
|
||||||
* `authentik_policies_reputation.reputation` - reputation
|
* `authentik_policies_reputation.reputation` - Reputation Score
|
||||||
* `authentik_policies.policybinding` - Policy Binding
|
* `authentik_policies.policybinding` - Policy Binding
|
||||||
* `authentik_providers_ldap.ldapprovider` - LDAP Provider
|
* `authentik_providers_ldap.ldapprovider` - LDAP Provider
|
||||||
* `authentik_providers_oauth2.scopemapping` - Scope Mapping
|
* `authentik_providers_oauth2.scopemapping` - Scope Mapping
|
||||||
|
@ -31943,7 +31943,7 @@ components:
|
||||||
* `authentik_policies_expression.expressionpolicy` - Expression Policy
|
* `authentik_policies_expression.expressionpolicy` - Expression Policy
|
||||||
* `authentik_policies_password.passwordpolicy` - Password Policy
|
* `authentik_policies_password.passwordpolicy` - Password Policy
|
||||||
* `authentik_policies_reputation.reputationpolicy` - Reputation Policy
|
* `authentik_policies_reputation.reputationpolicy` - Reputation Policy
|
||||||
* `authentik_policies_reputation.reputation` - reputation
|
* `authentik_policies_reputation.reputation` - Reputation Score
|
||||||
* `authentik_policies.policybinding` - Policy Binding
|
* `authentik_policies.policybinding` - Policy Binding
|
||||||
* `authentik_providers_ldap.ldapprovider` - LDAP Provider
|
* `authentik_providers_ldap.ldapprovider` - LDAP Provider
|
||||||
* `authentik_providers_oauth2.scopemapping` - Scope Mapping
|
* `authentik_providers_oauth2.scopemapping` - Scope Mapping
|
||||||
|
@ -34930,7 +34930,7 @@ components:
|
||||||
* `authentik_policies_expression.expressionpolicy` - Expression Policy
|
* `authentik_policies_expression.expressionpolicy` - Expression Policy
|
||||||
* `authentik_policies_password.passwordpolicy` - Password Policy
|
* `authentik_policies_password.passwordpolicy` - Password Policy
|
||||||
* `authentik_policies_reputation.reputationpolicy` - Reputation Policy
|
* `authentik_policies_reputation.reputationpolicy` - Reputation Policy
|
||||||
* `authentik_policies_reputation.reputation` - reputation
|
* `authentik_policies_reputation.reputation` - Reputation Score
|
||||||
* `authentik_policies.policybinding` - Policy Binding
|
* `authentik_policies.policybinding` - Policy Binding
|
||||||
* `authentik_providers_ldap.ldapprovider` - LDAP Provider
|
* `authentik_providers_ldap.ldapprovider` - LDAP Provider
|
||||||
* `authentik_providers_oauth2.scopemapping` - Scope Mapping
|
* `authentik_providers_oauth2.scopemapping` - Scope Mapping
|
||||||
|
|
|
@ -258,16 +258,18 @@ new?labels=bug,from_authentik&title=${encodeURIComponent(title)}
|
||||||
return html` <div class="pf-c-card__title">${msg("Secret:")}</div>
|
return html` <div class="pf-c-card__title">${msg("Secret:")}</div>
|
||||||
${this.getModelInfo(this.event.context.secret as EventModel)}`;
|
${this.getModelInfo(this.event.context.secret as EventModel)}`;
|
||||||
case EventActions.SystemException:
|
case EventActions.SystemException:
|
||||||
return html` <a
|
return html`<div class="pf-l-flex">
|
||||||
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">
|
|
||||||
<div class="pf-l-flex__item">
|
<div class="pf-l-flex__item">
|
||||||
<div class="pf-c-card__title">${msg("Exception")}</div>
|
<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">
|
<div class="pf-c-card__body">
|
||||||
<pre>${this.event.context.message}</pre>
|
<pre>${this.event.context.message}</pre>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -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_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
|
- `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
|
## Listen Setting
|
||||||
|
|
||||||
- `AUTHENTIK_LISTEN__HTTP`: Listening address:port (e.g. `0.0.0.0:9000`) for HTTP (Server and Proxy outpost)
|
- `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 (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 (LDAP 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 (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 (All)
|
- `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 (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 (Server)
|
- `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`.
|
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`.
|
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`
|
### `AUTHENTIK_WEB__WORKERS`
|
||||||
|
|
||||||
:::info
|
:::info
|
||||||
|
|
Reference in a new issue