policies: remove redundant policies which can be easily implemented with expressions
This commit is contained in:
parent
0f6dd33a6b
commit
7f3d0113c2
|
@ -24,13 +24,10 @@ from passbook.factors.otp.api import OTPFactorViewSet
|
|||
from passbook.factors.password.api import PasswordFactorViewSet
|
||||
from passbook.lib.utils.reflection import get_apps
|
||||
from passbook.policies.expiry.api import PasswordExpiryPolicyViewSet
|
||||
from passbook.policies.group.api import GroupMembershipPolicyViewSet
|
||||
from passbook.policies.expression.api import ExpressionPolicyViewSet
|
||||
from passbook.policies.hibp.api import HaveIBeenPwendPolicyViewSet
|
||||
from passbook.policies.matcher.api import FieldMatcherPolicyViewSet
|
||||
from passbook.policies.password.api import PasswordPolicyViewSet
|
||||
from passbook.policies.reputation.api import ReputationPolicyViewSet
|
||||
from passbook.policies.sso.api import SSOLoginPolicyViewSet
|
||||
from passbook.policies.webhook.api import WebhookPolicyViewSet
|
||||
from passbook.providers.app_gw.api import ApplicationGatewayProviderViewSet
|
||||
from passbook.providers.oauth.api import OAuth2ProviderViewSet
|
||||
|
@ -58,12 +55,9 @@ router.register("sources/ldap", LDAPSourceViewSet)
|
|||
router.register("sources/oauth", OAuthSourceViewSet)
|
||||
router.register("policies/all", PolicyViewSet)
|
||||
router.register("policies/passwordexpiry", PasswordExpiryPolicyViewSet)
|
||||
router.register("policies/groupmembership", GroupMembershipPolicyViewSet)
|
||||
router.register("policies/haveibeenpwned", HaveIBeenPwendPolicyViewSet)
|
||||
router.register("policies/fieldmatcher", FieldMatcherPolicyViewSet)
|
||||
router.register("policies/password", PasswordPolicyViewSet)
|
||||
router.register("policies/reputation", ReputationPolicyViewSet)
|
||||
router.register("policies/ssologin", SSOLoginPolicyViewSet)
|
||||
router.register("policies/webhook", WebhookPolicyViewSet)
|
||||
router.register("policies/expression", ExpressionPolicyViewSet)
|
||||
router.register("providers/all", ProviderViewSet)
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
"""autodiscover admin"""
|
||||
from passbook.lib.admin import admin_autoregister
|
||||
|
||||
admin_autoregister("passbook_policies_group")
|
|
@ -1,21 +0,0 @@
|
|||
"""Source API Views"""
|
||||
from rest_framework.serializers import ModelSerializer
|
||||
from rest_framework.viewsets import ModelViewSet
|
||||
|
||||
from passbook.policies.forms import GENERAL_SERIALIZER_FIELDS
|
||||
from passbook.policies.group.models import GroupMembershipPolicy
|
||||
|
||||
|
||||
class GroupMembershipPolicySerializer(ModelSerializer):
|
||||
"""Group Membership Policy Serializer"""
|
||||
|
||||
class Meta:
|
||||
model = GroupMembershipPolicy
|
||||
fields = GENERAL_SERIALIZER_FIELDS + ["group"]
|
||||
|
||||
|
||||
class GroupMembershipPolicyViewSet(ModelViewSet):
|
||||
"""Source Viewset"""
|
||||
|
||||
queryset = GroupMembershipPolicy.objects.all()
|
||||
serializer_class = GroupMembershipPolicySerializer
|
|
@ -1,11 +0,0 @@
|
|||
"""passbook Group policy app config"""
|
||||
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class PassbookPoliciesGroupConfig(AppConfig):
|
||||
"""passbook Group policy app config"""
|
||||
|
||||
name = "passbook.policies.group"
|
||||
label = "passbook_policies_group"
|
||||
verbose_name = "passbook Policies.Group"
|
|
@ -1,21 +0,0 @@
|
|||
"""passbook Policy forms"""
|
||||
|
||||
from django import forms
|
||||
|
||||
from passbook.policies.forms import GENERAL_FIELDS
|
||||
from passbook.policies.group.models import GroupMembershipPolicy
|
||||
|
||||
|
||||
class GroupMembershipPolicyForm(forms.ModelForm):
|
||||
"""GroupMembershipPolicy Form"""
|
||||
|
||||
class Meta:
|
||||
|
||||
model = GroupMembershipPolicy
|
||||
fields = GENERAL_FIELDS + [
|
||||
"group",
|
||||
]
|
||||
widgets = {
|
||||
"name": forms.TextInput(),
|
||||
"order": forms.NumberInput(),
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
# Generated by Django 2.2.6 on 2019-10-07 14:07
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
("passbook_core", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="GroupMembershipPolicy",
|
||||
fields=[
|
||||
(
|
||||
"policy_ptr",
|
||||
models.OneToOneField(
|
||||
auto_created=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
parent_link=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
to="passbook_core.Policy",
|
||||
),
|
||||
),
|
||||
(
|
||||
"group",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to="passbook_core.Group",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "Group Membership Policy",
|
||||
"verbose_name_plural": "Group Membership Policies",
|
||||
},
|
||||
bases=("passbook_core.policy",),
|
||||
),
|
||||
]
|
|
@ -1,22 +0,0 @@
|
|||
"""passbook group models models"""
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from passbook.core.models import Group, Policy
|
||||
from passbook.policies.struct import PolicyRequest, PolicyResult
|
||||
|
||||
|
||||
class GroupMembershipPolicy(Policy):
|
||||
"""Policy to check if the user is member in a certain group"""
|
||||
|
||||
group = models.ForeignKey(Group, on_delete=models.CASCADE)
|
||||
|
||||
form = "passbook.policies.group.forms.GroupMembershipPolicyForm"
|
||||
|
||||
def passes(self, request: PolicyRequest) -> PolicyResult:
|
||||
return PolicyResult(self.group.user_set.filter(pk=request.user.pk).exists())
|
||||
|
||||
class Meta:
|
||||
|
||||
verbose_name = _("Group Membership Policy")
|
||||
verbose_name_plural = _("Group Membership Policies")
|
|
@ -1,4 +0,0 @@
|
|||
"""autodiscover admin"""
|
||||
from passbook.lib.admin import admin_autoregister
|
||||
|
||||
admin_autoregister("passbook_policies_matcher")
|
|
@ -1,25 +0,0 @@
|
|||
"""Source API Views"""
|
||||
from rest_framework.serializers import ModelSerializer
|
||||
from rest_framework.viewsets import ModelViewSet
|
||||
|
||||
from passbook.policies.forms import GENERAL_SERIALIZER_FIELDS
|
||||
from passbook.policies.matcher.models import FieldMatcherPolicy
|
||||
|
||||
|
||||
class FieldMatcherPolicySerializer(ModelSerializer):
|
||||
"""Field Matcher Policy Serializer"""
|
||||
|
||||
class Meta:
|
||||
model = FieldMatcherPolicy
|
||||
fields = GENERAL_SERIALIZER_FIELDS + [
|
||||
"user_field",
|
||||
"match_action",
|
||||
"value",
|
||||
]
|
||||
|
||||
|
||||
class FieldMatcherPolicyViewSet(ModelViewSet):
|
||||
"""Source Viewset"""
|
||||
|
||||
queryset = FieldMatcherPolicy.objects.all()
|
||||
serializer_class = FieldMatcherPolicySerializer
|
|
@ -1,11 +0,0 @@
|
|||
"""passbook Matcher policy app config"""
|
||||
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class PassbookPoliciesMatcherConfig(AppConfig):
|
||||
"""passbook Matcher policy app config"""
|
||||
|
||||
name = "passbook.policies.matcher"
|
||||
label = "passbook_policies_matcher"
|
||||
verbose_name = "passbook Policies.Matcher"
|
|
@ -1,23 +0,0 @@
|
|||
"""passbook Policy forms"""
|
||||
|
||||
from django import forms
|
||||
|
||||
from passbook.policies.forms import GENERAL_FIELDS
|
||||
from passbook.policies.matcher.models import FieldMatcherPolicy
|
||||
|
||||
|
||||
class FieldMatcherPolicyForm(forms.ModelForm):
|
||||
"""FieldMatcherPolicy Form"""
|
||||
|
||||
class Meta:
|
||||
|
||||
model = FieldMatcherPolicy
|
||||
fields = GENERAL_FIELDS + [
|
||||
"user_field",
|
||||
"match_action",
|
||||
"value",
|
||||
]
|
||||
widgets = {
|
||||
"name": forms.TextInput(),
|
||||
"value": forms.TextInput(),
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
# Generated by Django 2.2.6 on 2019-10-07 14:07
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
("passbook_core", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="FieldMatcherPolicy",
|
||||
fields=[
|
||||
(
|
||||
"policy_ptr",
|
||||
models.OneToOneField(
|
||||
auto_created=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
parent_link=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
to="passbook_core.Policy",
|
||||
),
|
||||
),
|
||||
(
|
||||
"user_field",
|
||||
models.TextField(
|
||||
choices=[
|
||||
("username", "Username"),
|
||||
("name", "Name"),
|
||||
("email", "E-Mail"),
|
||||
("is_staff", "Is staff"),
|
||||
("is_active", "Is active"),
|
||||
("data_joined", "Date joined"),
|
||||
]
|
||||
),
|
||||
),
|
||||
(
|
||||
"match_action",
|
||||
models.CharField(
|
||||
choices=[
|
||||
("startswith", "Starts with"),
|
||||
("endswith", "Ends with"),
|
||||
("contains", "Contains"),
|
||||
("regexp", "Regexp"),
|
||||
("exact", "Exact"),
|
||||
],
|
||||
max_length=50,
|
||||
),
|
||||
),
|
||||
("value", models.TextField()),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "Field matcher Policy",
|
||||
"verbose_name_plural": "Field matcher Policies",
|
||||
},
|
||||
bases=("passbook_core.policy",),
|
||||
),
|
||||
]
|
|
@ -1,83 +0,0 @@
|
|||
"""user field matcher models"""
|
||||
import re
|
||||
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext as _
|
||||
from structlog import get_logger
|
||||
|
||||
from passbook.core.models import Policy
|
||||
from passbook.policies.struct import PolicyRequest, PolicyResult
|
||||
|
||||
LOGGER = get_logger()
|
||||
|
||||
|
||||
class FieldMatcherPolicy(Policy):
|
||||
"""Policy which checks if a field of the User model matches/doesn't match a
|
||||
certain pattern"""
|
||||
|
||||
MATCH_STARTSWITH = "startswith"
|
||||
MATCH_ENDSWITH = "endswith"
|
||||
MATCH_CONTAINS = "contains"
|
||||
MATCH_REGEXP = "regexp"
|
||||
MATCH_EXACT = "exact"
|
||||
|
||||
MATCHES = (
|
||||
(MATCH_STARTSWITH, _("Starts with")),
|
||||
(MATCH_ENDSWITH, _("Ends with")),
|
||||
(MATCH_CONTAINS, _("Contains")),
|
||||
(MATCH_REGEXP, _("Regexp")),
|
||||
(MATCH_EXACT, _("Exact")),
|
||||
)
|
||||
|
||||
USER_FIELDS = (
|
||||
("username", _("Username"),),
|
||||
("name", _("Name"),),
|
||||
("email", _("E-Mail"),),
|
||||
("is_staff", _("Is staff"),),
|
||||
("is_active", _("Is active"),),
|
||||
("data_joined", _("Date joined"),),
|
||||
)
|
||||
|
||||
user_field = models.TextField(choices=USER_FIELDS)
|
||||
match_action = models.CharField(max_length=50, choices=MATCHES)
|
||||
value = models.TextField()
|
||||
|
||||
form = "passbook.policies.matcher.forms.FieldMatcherPolicyForm"
|
||||
|
||||
def __str__(self):
|
||||
description = (
|
||||
f"{self.name}, user.{self.user_field} {self.match_action} '{self.value}'"
|
||||
)
|
||||
if self.name:
|
||||
description = f"{self.name}: {description}"
|
||||
return description
|
||||
|
||||
def passes(self, request: PolicyRequest) -> PolicyResult:
|
||||
"""Check if user instance passes this role"""
|
||||
if not hasattr(request.user, self.user_field):
|
||||
raise ValueError("Field does not exist")
|
||||
user_field_value = getattr(request.user, self.user_field, None)
|
||||
LOGGER.debug(
|
||||
"Checking field",
|
||||
value=user_field_value,
|
||||
action=self.match_action,
|
||||
should_be=self.value,
|
||||
)
|
||||
passes = False
|
||||
if self.match_action == FieldMatcherPolicy.MATCH_STARTSWITH:
|
||||
passes = user_field_value.startswith(self.value)
|
||||
if self.match_action == FieldMatcherPolicy.MATCH_ENDSWITH:
|
||||
passes = user_field_value.endswith(self.value)
|
||||
if self.match_action == FieldMatcherPolicy.MATCH_CONTAINS:
|
||||
passes = self.value in user_field_value
|
||||
if self.match_action == FieldMatcherPolicy.MATCH_REGEXP:
|
||||
pattern = re.compile(self.value)
|
||||
passes = bool(pattern.match(user_field_value))
|
||||
if self.match_action == FieldMatcherPolicy.MATCH_EXACT:
|
||||
passes = user_field_value == self.value
|
||||
return PolicyResult(passes)
|
||||
|
||||
class Meta:
|
||||
|
||||
verbose_name = _("Field matcher Policy")
|
||||
verbose_name_plural = _("Field matcher Policies")
|
|
@ -1,4 +0,0 @@
|
|||
"""autodiscover admin"""
|
||||
from passbook.lib.admin import admin_autoregister
|
||||
|
||||
admin_autoregister("passbook_policies_sso")
|
|
@ -1,21 +0,0 @@
|
|||
"""Source API Views"""
|
||||
from rest_framework.serializers import ModelSerializer
|
||||
from rest_framework.viewsets import ModelViewSet
|
||||
|
||||
from passbook.policies.forms import GENERAL_SERIALIZER_FIELDS
|
||||
from passbook.policies.sso.models import SSOLoginPolicy
|
||||
|
||||
|
||||
class SSOLoginPolicySerializer(ModelSerializer):
|
||||
"""SSO Login Policy Serializer"""
|
||||
|
||||
class Meta:
|
||||
model = SSOLoginPolicy
|
||||
fields = GENERAL_SERIALIZER_FIELDS
|
||||
|
||||
|
||||
class SSOLoginPolicyViewSet(ModelViewSet):
|
||||
"""Source Viewset"""
|
||||
|
||||
queryset = SSOLoginPolicy.objects.all()
|
||||
serializer_class = SSOLoginPolicySerializer
|
|
@ -1,11 +0,0 @@
|
|||
"""passbook sso policy app config"""
|
||||
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class PassbookPoliciesSSOConfig(AppConfig):
|
||||
"""passbook sso policy app config"""
|
||||
|
||||
name = "passbook.policies.sso"
|
||||
label = "passbook_policies_sso"
|
||||
verbose_name = "passbook Policies.SSO"
|
|
@ -1,19 +0,0 @@
|
|||
"""passbook Policy forms"""
|
||||
|
||||
from django import forms
|
||||
|
||||
from passbook.policies.forms import GENERAL_FIELDS
|
||||
from passbook.policies.sso.models import SSOLoginPolicy
|
||||
|
||||
|
||||
class SSOLoginPolicyForm(forms.ModelForm):
|
||||
"""Edit SSOLoginPolicy instances"""
|
||||
|
||||
class Meta:
|
||||
|
||||
model = SSOLoginPolicy
|
||||
fields = GENERAL_FIELDS
|
||||
widgets = {
|
||||
"name": forms.TextInput(),
|
||||
"order": forms.NumberInput(),
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
# Generated by Django 2.2.6 on 2019-10-07 14:07
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
("passbook_core", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="SSOLoginPolicy",
|
||||
fields=[
|
||||
(
|
||||
"policy_ptr",
|
||||
models.OneToOneField(
|
||||
auto_created=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
parent_link=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
to="passbook_core.Policy",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "SSO Login Policy",
|
||||
"verbose_name_plural": "SSO Login Policies",
|
||||
},
|
||||
bases=("passbook_core.policy",),
|
||||
),
|
||||
]
|
|
@ -1,25 +0,0 @@
|
|||
"""sso models"""
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from passbook.core.models import Policy
|
||||
from passbook.policies.struct import PolicyRequest, PolicyResult
|
||||
|
||||
|
||||
class SSOLoginPolicy(Policy):
|
||||
"""Policy that applies to users that have authenticated themselves through SSO"""
|
||||
|
||||
form = "passbook.policies.sso.forms.SSOLoginPolicyForm"
|
||||
|
||||
def passes(self, request: PolicyRequest) -> PolicyResult:
|
||||
"""Check if user instance passes this policy"""
|
||||
from passbook.factors.view import AuthenticationView
|
||||
|
||||
is_sso_login = request.user.session.get(
|
||||
AuthenticationView.SESSION_IS_SSO_LOGIN, False
|
||||
)
|
||||
return PolicyResult(is_sso_login)
|
||||
|
||||
class Meta:
|
||||
|
||||
verbose_name = _("SSO Login Policy")
|
||||
verbose_name_plural = _("SSO Login Policies")
|
|
@ -93,10 +93,7 @@ INSTALLED_APPS = [
|
|||
"passbook.policies.expiry.apps.PassbookPolicyExpiryConfig",
|
||||
"passbook.policies.reputation.apps.PassbookPolicyReputationConfig",
|
||||
"passbook.policies.hibp.apps.PassbookPolicyHIBPConfig",
|
||||
"passbook.policies.group.apps.PassbookPoliciesGroupConfig",
|
||||
"passbook.policies.matcher.apps.PassbookPoliciesMatcherConfig",
|
||||
"passbook.policies.password.apps.PassbookPoliciesPasswordConfig",
|
||||
"passbook.policies.sso.apps.PassbookPoliciesSSOConfig",
|
||||
"passbook.policies.webhook.apps.PassbookPoliciesWebhookConfig",
|
||||
"passbook.policies.expression.apps.PassbookPolicyExpressionConfig",
|
||||
]
|
||||
|
|
Reference in New Issue