all(major): add most models to API

This commit is contained in:
Langhammer, Jens 2019-10-28 17:40:57 +01:00
parent 846a86fb62
commit cffe09b02e
27 changed files with 606 additions and 46 deletions

View File

@ -10,7 +10,7 @@ defusedxml = "*"
django = "*" django = "*"
kombu = "==4.5.0" kombu = "==4.5.0"
django-cors-middleware = "*" django-cors-middleware = "*"
django-filters = "*" django-filter = "*"
django-ipware = "*" django-ipware = "*"
django-model-utils = "*" django-model-utils = "*"
django-oauth-toolkit = "*" django-oauth-toolkit = "*"
@ -41,6 +41,7 @@ django-guardian = "*"
django-dbbackup = "*" django-dbbackup = "*"
boto3 = "*" boto3 = "*"
django-storages = "*" django-storages = "*"
swagger-spec-validator = "*"
[requires] [requires]
python_version = "3.7" python_version = "3.7"

91
Pipfile.lock generated
View File

@ -1,7 +1,7 @@
{ {
"_meta": { "_meta": {
"hash": { "hash": {
"sha256": "fa76852e940fed079700de54816889e85ca1f59213210efc2537d38a9086c010" "sha256": "045f299c421b29003cbc657397d79fcb1c16a0bce9991aaeadc76f55339f7f09"
}, },
"pipfile-spec": 6, "pipfile-spec": 6,
"requires": { "requires": {
@ -204,12 +204,13 @@
"index": "pypi", "index": "pypi",
"version": "==3.2.0" "version": "==3.2.0"
}, },
"django-filters": { "django-filter": {
"hashes": [ "hashes": [
"sha256:1a9799a41106dc53ed894e952a24e8dee9b4fb37f010f22d178c09c90c61d711" "sha256:558c727bce3ffa89c4a7a0b13bc8976745d63e5fd576b3a9a851650ef11c401b",
"sha256:c3deb57f0dd7ff94d7dce52a047516822013e2b441bed472b722a317658cfd14"
], ],
"index": "pypi", "index": "pypi",
"version": "==0.2.1" "version": "==2.2.0"
}, },
"django-guardian": { "django-guardian": {
"hashes": [ "hashes": [
@ -338,6 +339,13 @@
], ],
"version": "==2.8" "version": "==2.8"
}, },
"importlib-metadata": {
"hashes": [
"sha256:aa18d7378b00b40847790e7c27e11673d7fed219354109d0e7b9e5b25dc3ad26",
"sha256:d5f18a79777f3aa179c145737780282e27b508fc8fd688cb17c7a813e8bd39af"
],
"version": "==0.23"
},
"inflection": { "inflection": {
"hashes": [ "hashes": [
"sha256:18ea7fb7a7d152853386523def08736aa8c32636b047ade55f7578c4edeb16ca" "sha256:18ea7fb7a7d152853386523def08736aa8c32636b047ade55f7578c4edeb16ca"
@ -371,6 +379,13 @@
], ],
"version": "==0.9.4" "version": "==0.9.4"
}, },
"jsonschema": {
"hashes": [
"sha256:2fa0684276b6333ff3c0b1b27081f4b2305f0a36cf702a23db50edb141893c3f",
"sha256:94c0a13b4a0616458b42529091624e66700a17f847453e52279e35509a5b7631"
],
"version": "==3.1.1"
},
"kombu": { "kombu": {
"hashes": [ "hashes": [
"sha256:389ba09e03b15b55b1a7371a441c894fd8121d174f5583bbbca032b9ea8c9edd", "sha256:389ba09e03b15b55b1a7371a441c894fd8121d174f5583bbbca032b9ea8c9edd",
@ -392,6 +407,7 @@
"sha256:02ca7bf899da57084041bb0f6095333e4d239948ad3169443f454add9f4e9cb4", "sha256:02ca7bf899da57084041bb0f6095333e4d239948ad3169443f454add9f4e9cb4",
"sha256:096b82c5e0ea27ce9138bcbb205313343ee66a6e132f25c5ed67e2c8d960a1bc", "sha256:096b82c5e0ea27ce9138bcbb205313343ee66a6e132f25c5ed67e2c8d960a1bc",
"sha256:0a920ff98cf1aac310470c644bc23b326402d3ef667ddafecb024e1713d485f1", "sha256:0a920ff98cf1aac310470c644bc23b326402d3ef667ddafecb024e1713d485f1",
"sha256:1409b14bf83a7d729f92e2a7fbfe7ec929d4883ca071b06e95c539ceedb6497c",
"sha256:17cae1730a782858a6e2758fd20dd0ef7567916c47757b694a06ffafdec20046", "sha256:17cae1730a782858a6e2758fd20dd0ef7567916c47757b694a06ffafdec20046",
"sha256:17e3950add54c882e032527795c625929613adbd2ce5162b94667334458b5a36", "sha256:17e3950add54c882e032527795c625929613adbd2ce5162b94667334458b5a36",
"sha256:1f4f214337f6ee5825bf90a65d04d70aab05526c08191ab888cb5149501923c5", "sha256:1f4f214337f6ee5825bf90a65d04d70aab05526c08191ab888cb5149501923c5",
@ -402,11 +418,14 @@
"sha256:760c12276fee05c36f95f8040180abc7fbebb9e5011447a97cdc289b5d6ab6fc", "sha256:760c12276fee05c36f95f8040180abc7fbebb9e5011447a97cdc289b5d6ab6fc",
"sha256:796685d3969815a633827c818863ee199440696b0961e200b011d79b9394bbe7", "sha256:796685d3969815a633827c818863ee199440696b0961e200b011d79b9394bbe7",
"sha256:891fe897b49abb7db470c55664b198b1095e4943b9f82b7dcab317a19116cd38", "sha256:891fe897b49abb7db470c55664b198b1095e4943b9f82b7dcab317a19116cd38",
"sha256:9277562f175d2334744ad297568677056861070399cec56ff06abbe2564d1232",
"sha256:a471628e20f03dcdfde00770eeaf9c77811f0c331c8805219ca7b87ac17576c5", "sha256:a471628e20f03dcdfde00770eeaf9c77811f0c331c8805219ca7b87ac17576c5",
"sha256:a63b4fd3e2cabdcc9d918ed280bdde3e8e9641e04f3c59a2a3109644a07b9832", "sha256:a63b4fd3e2cabdcc9d918ed280bdde3e8e9641e04f3c59a2a3109644a07b9832",
"sha256:ae88588d687bd476be588010cbbe551e9c2872b816f2da8f01f6f1fda74e1ef0",
"sha256:b0b84408d4eabc6de9dd1e1e0bc63e7731e890c0b378a62443e5741cfd0ae90a", "sha256:b0b84408d4eabc6de9dd1e1e0bc63e7731e890c0b378a62443e5741cfd0ae90a",
"sha256:be78485e5d5f3684e875dab60f40cddace2f5b2a8f7fede412358ab3214c3a6f", "sha256:be78485e5d5f3684e875dab60f40cddace2f5b2a8f7fede412358ab3214c3a6f",
"sha256:c27eaed872185f047bb7f7da2d21a7d8913457678c9a100a50db6da890bc28b9", "sha256:c27eaed872185f047bb7f7da2d21a7d8913457678c9a100a50db6da890bc28b9",
"sha256:c7fccd08b14aa437fe096c71c645c0f9be0655a9b1a4b7cffc77bcb23b3d61d2",
"sha256:c81cb40bff373ab7a7446d6bbca0190bccc5be3448b47b51d729e37799bb5692", "sha256:c81cb40bff373ab7a7446d6bbca0190bccc5be3448b47b51d729e37799bb5692",
"sha256:d11874b3c33ee441059464711cd365b89fa1a9cf19ae75b0c189b01fbf735b84", "sha256:d11874b3c33ee441059464711cd365b89fa1a9cf19ae75b0c189b01fbf735b84",
"sha256:e9c028b5897901361d81a4718d1db217b716424a0283afe9d6735fe0caf70f79", "sha256:e9c028b5897901361d81a4718d1db217b716424a0283afe9d6735fe0caf70f79",
@ -629,6 +648,12 @@
], ],
"version": "==2.4.2" "version": "==2.4.2"
}, },
"pyrsistent": {
"hashes": [
"sha256:eb6545dbeb1aa69ab1fb4809bfbf5a8705e44d92ef8fc7c2361682a47c46c778"
],
"version": "==0.15.5"
},
"python-dateutil": { "python-dateutil": {
"hashes": [ "hashes": [
"sha256:7e6584c74aeed623791615e26efd690f29817a27c73085b78e4bad02493df2fb", "sha256:7e6584c74aeed623791615e26efd690f29817a27c73085b78e4bad02493df2fb",
@ -659,6 +684,7 @@
"sha256:861c94442b28cd64af033e88e0f63c66dbd5609f67952dc18694098b47a43f3a", "sha256:861c94442b28cd64af033e88e0f63c66dbd5609f67952dc18694098b47a43f3a",
"sha256:957bc6316ffc8463795d56d9953d58e7f32aa5aad1c5ac80bc45c69f3299961e", "sha256:957bc6316ffc8463795d56d9953d58e7f32aa5aad1c5ac80bc45c69f3299961e",
"sha256:9760c3f56fb5f15852d163429096600906478e9ed2c189a52f2bb21d8a2a986c", "sha256:9760c3f56fb5f15852d163429096600906478e9ed2c189a52f2bb21d8a2a986c",
"sha256:9fdfb98a2992de01e8efad2aeed22c825e36db628b144b2d6b93d81fb549f811",
"sha256:a4b24703ea818196d0be1dc64b3b57b79c67e8dee0cfa207a4216220912035a7", "sha256:a4b24703ea818196d0be1dc64b3b57b79c67e8dee0cfa207a4216220912035a7",
"sha256:ad7f4968c1ddbf139a306d9b075360d959cc554d994ba5e1f512af9a40e62357", "sha256:ad7f4968c1ddbf139a306d9b075360d959cc554d994ba5e1f512af9a40e62357",
"sha256:b1127d34b90f74faf1707718c57a4193ac028b9f4aec0238638983132297d456", "sha256:b1127d34b90f74faf1707718c57a4193ac028b9f4aec0238638983132297d456",
@ -669,6 +695,7 @@
"sha256:ce777ebdf49ce736fc04abf555b5c41ab3f130127543a689dcf8d4871cd18fe4", "sha256:ce777ebdf49ce736fc04abf555b5c41ab3f130127543a689dcf8d4871cd18fe4",
"sha256:d8b4bf930b6a19bc9ee982b9163d948c87501ad91b71516924e8ed25fe85d2ee", "sha256:d8b4bf930b6a19bc9ee982b9163d948c87501ad91b71516924e8ed25fe85d2ee",
"sha256:e2a420f2c4d35f3ec0b7e752a80d7bd385e2c5a64f67c05f2d2d74230e3114b6", "sha256:e2a420f2c4d35f3ec0b7e752a80d7bd385e2c5a64f67c05f2d2d74230e3114b6",
"sha256:ef5eb630f541af6b69378d58594be90a0922fa6d6a50a9248c25b9502585f6bf",
"sha256:fed899ce96f4f2b4d1b9f338dd145a4040ee1d8a5152213af0dd8d4a4d36e9fe" "sha256:fed899ce96f4f2b4d1b9f338dd145a4040ee1d8a5152213af0dd8d4a4d36e9fe"
], ],
"index": "pypi", "index": "pypi",
@ -807,6 +834,14 @@
"index": "pypi", "index": "pypi",
"version": "==19.2.0" "version": "==19.2.0"
}, },
"swagger-spec-validator": {
"hashes": [
"sha256:57e29feb3aa921a9fb98bd70af148746b27c77d3207266f5571cebcce211e685",
"sha256:62ef22eca3f429d93fddda5d793d2a1a9057d3732e7a14606e641805326ae4a6"
],
"index": "pypi",
"version": "==2.4.3"
},
"tempora": { "tempora": {
"hashes": [ "hashes": [
"sha256:cb60b1d2b1664104e307f8e5269d7f4acdb077c82e35cd57246ae14a3427d2d6", "sha256:cb60b1d2b1664104e307f8e5269d7f4acdb077c82e35cd57246ae14a3427d2d6",
@ -847,6 +882,13 @@
"sha256:cc33599b549f0c8a248cb72f3bf32d77712de1ff7ee8814312eb6456b42c015f" "sha256:cc33599b549f0c8a248cb72f3bf32d77712de1ff7ee8814312eb6456b42c015f"
], ],
"version": "==2.0" "version": "==2.0"
},
"zipp": {
"hashes": [
"sha256:3718b1cbcd963c7d4c5511a8240812904164b7f381b647143a89d3b98f9bcd8e",
"sha256:f06903e9f1f43b12d371004b4ac7b06ab39a44adc747266928ae6debfa7b3335"
],
"version": "==0.6.0"
} }
}, },
"develop": { "develop": {
@ -972,26 +1014,29 @@
}, },
"lazy-object-proxy": { "lazy-object-proxy": {
"hashes": [ "hashes": [
"sha256:02b260c8deb80db09325b99edf62ae344ce9bc64d68b7a634410b8e9a568edbf", "sha256:0c4b206227a8097f05c4dbdd323c50edf81f15db3b8dc064d08c62d37e1a504d",
"sha256:18f9c401083a4ba6e162355873f906315332ea7035803d0fd8166051e3d402e3", "sha256:194d092e6f246b906e8f70884e620e459fc54db3259e60cf69a4d66c3fda3449",
"sha256:1f2c6209a8917c525c1e2b55a716135ca4658a3042b5122d4e3413a4030c26ce", "sha256:1be7e4c9f96948003609aa6c974ae59830a6baecc5376c25c92d7d697e684c08",
"sha256:2f06d97f0ca0f414f6b707c974aaf8829c2292c1c497642f63824119d770226f", "sha256:4677f594e474c91da97f489fea5b7daa17b5517190899cf213697e48d3902f5a",
"sha256:616c94f8176808f4018b39f9638080ed86f96b55370b5a9463b2ee5c926f6c5f", "sha256:48dab84ebd4831077b150572aec802f303117c8cc5c871e182447281ebf3ac50",
"sha256:63b91e30ef47ef68a30f0c3c278fbfe9822319c15f34b7538a829515b84ca2a0", "sha256:5541cada25cd173702dbd99f8e22434105456314462326f06dba3e180f203dfd",
"sha256:77b454f03860b844f758c5d5c6e5f18d27de899a3db367f4af06bec2e6013a8e", "sha256:59f79fef100b09564bc2df42ea2d8d21a64fdcda64979c0fa3db7bdaabaf6239",
"sha256:83fe27ba321e4cfac466178606147d3c0aa18e8087507caec78ed5a966a64905", "sha256:8d859b89baf8ef7f8bc6b00aa20316483d67f0b1cbf422f5b4dc56701c8f2ffb",
"sha256:84742532d39f72df959d237912344d8a1764c2d03fe58beba96a87bfa11a76d8", "sha256:9254f4358b9b541e3441b007a0ea0764b9d056afdeafc1a5569eee1cc6c1b9ea",
"sha256:874ebf3caaf55a020aeb08acead813baf5a305927a71ce88c9377970fe7ad3c2", "sha256:9651375199045a358eb6741df3e02a651e0330be090b3bc79f6d0de31a80ec3e",
"sha256:9f5caf2c7436d44f3cec97c2fa7791f8a675170badbfa86e1992ca1b84c37009", "sha256:97bb5884f6f1cdce0099f86b907aa41c970c3c672ac8b9c8352789e103cf3156",
"sha256:a0c8758d01fcdfe7ae8e4b4017b13552efa7f1197dd7358dc9da0576f9d0328a", "sha256:9b15f3f4c0f35727d3a0fba4b770b3c4ebbb1fa907dbcc046a1d2799f3edd142",
"sha256:a4def978d9d28cda2d960c279318d46b327632686d82b4917516c36d4c274512", "sha256:a2238e9d1bb71a56cd710611a1614d1194dc10a175c1e08d75e1a7bcc250d442",
"sha256:ad4f4be843dace866af5fc142509e9b9817ca0c59342fdb176ab6ad552c927f5", "sha256:a6ae12d08c0bf9909ce12385803a543bfe99b95fe01e752536a60af2b7797c62",
"sha256:ae33dd198f772f714420c5ab698ff05ff900150486c648d29951e9c70694338e", "sha256:ca0a928a3ddbc5725be2dd1cf895ec0a254798915fb3a36af0964a0a4149e3db",
"sha256:b4a2b782b8a8c5522ad35c93e04d60e2ba7f7dcb9271ec8e8c3e08239be6c7b4", "sha256:cb2c7c57005a6804ab66f106ceb8482da55f5314b7fcb06551db1edae4ad1531",
"sha256:c462eb33f6abca3b34cdedbe84d761f31a60b814e173b98ede3c81bb48967c4f", "sha256:d74bb8693bf9cf75ac3b47a54d716bbb1a92648d5f781fc799347cfc95952383",
"sha256:fd135b8d35dfdcdb984828c84d695937e58cc5f49e1c854eb311c4d6aa03f4f1" "sha256:d945239a5639b3ff35b70a88c5f2f491913eb94871780ebfabb2568bd58afc5a",
"sha256:eba7011090323c1dadf18b3b689845fd96a61ba0a1dfbd7f24b921398affc357",
"sha256:efa1909120ce98bbb3777e8b6f92237f5d5c8ea6758efea36a473e1d38f7d3e4",
"sha256:f3900e8a5de27447acbf900b4750b0ddfd7ec1ea7fbaf11dfa911141bc522af0"
], ],
"version": "==1.4.2" "version": "==1.4.3"
}, },
"mccabe": { "mccabe": {
"hashes": [ "hashes": [

View File

@ -2,5 +2,6 @@
# from django import forms # from django import forms
SOURCE_FORM_FIELDS = ['name', 'slug', 'enabled', 'policies'] SOURCE_FORM_FIELDS = ['name', 'slug', 'enabled', 'policies']
SOURCE_SERIALIZER_FIELDS = ['pk', 'name', 'slug', 'enabled', 'policies']
# class SourceForm(forms.Form) # class SourceForm(forms.Form)

View File

@ -25,5 +25,7 @@ class PolicyPermissions(BasePermission):
policy_engine: PolicyEngine policy_engine: PolicyEngine
def has_object_permission(self, request, view, obj: PolicyModel) -> bool: def has_object_permission(self, request, view, obj: PolicyModel) -> bool:
# if not obj.po
self.policy_engine = PolicyEngine(obj.policies, request.user, request) self.policy_engine = PolicyEngine(obj.policies, request.user, request)
self.policy_engine.request.obj = obj
return self.policy_engine.build().passing return self.policy_engine.build().passing

View File

@ -1,16 +1,85 @@
"""api v2 urls""" """api v2 urls"""
from django.conf.urls import url
from django.urls import path
from drf_yasg import openapi
from drf_yasg.views import get_schema_view
from rest_framework import routers from rest_framework import routers
from structlog import get_logger
from passbook.api.permissions import CustomObjectPermissions
from passbook.audit.api.events import EventViewSet from passbook.audit.api.events import EventViewSet
from passbook.core.api.applications import ApplicationViewSet from passbook.core.api.applications import ApplicationViewSet
from passbook.core.api.groups import GroupViewSet from passbook.core.api.groups import GroupViewSet
from passbook.core.api.invitations import InvitationViewSet from passbook.core.api.invitations import InvitationViewSet
from passbook.core.api.policies import PolicyViewSet
from passbook.core.api.providers import ProviderViewSet
from passbook.core.api.sources import SourceViewSet
from passbook.core.api.users import UserViewSet from passbook.core.api.users import UserViewSet
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.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
from passbook.providers.oidc.api import OpenIDProviderViewSet
from passbook.providers.saml.api import SAMLProviderViewSet
from passbook.sources.ldap.api import LDAPSourceViewSet
from passbook.sources.oauth.api import OAuthSourceViewSet
LOGGER = get_logger()
router = routers.DefaultRouter() router = routers.DefaultRouter()
for _passbook_app in get_apps():
if hasattr(_passbook_app, 'api_mountpoint'):
for prefix, viewset in _passbook_app.api_mountpoint:
router.register(prefix, viewset)
LOGGER.debug("Mounted API URLs", app_name=_passbook_app.name)
router.register('core/applications', ApplicationViewSet) router.register('core/applications', ApplicationViewSet)
router.register('core/invitations', InvitationViewSet) router.register('core/invitations', InvitationViewSet)
router.register('core/groups', GroupViewSet) router.register('core/groups', GroupViewSet)
router.register('core/users', UserViewSet) router.register('core/users', UserViewSet)
router.register('audit/events', EventViewSet) router.register('audit/events', EventViewSet)
urlpatterns = router.urls router.register('sources/all', SourceViewSet)
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('providers/all', ProviderViewSet)
router.register('providers/applicationgateway', ApplicationGatewayProviderViewSet)
router.register('providers/oauth', OAuth2ProviderViewSet)
router.register('providers/openid', OpenIDProviderViewSet)
router.register('providers/saml', SAMLProviderViewSet)
info = openapi.Info(
title="passbook API",
default_version='v2',
# description="Test description",
# terms_of_service="https://www.google.com/policies/terms/",
contact=openapi.Contact(email="hello@beryju.org"),
license=openapi.License(name="MIT License"),
)
SchemaView = get_schema_view(
info,
public=True,
permission_classes=(CustomObjectPermissions,),
)
urlpatterns = [
url(r'^swagger(?P<format>\.json|\.yaml)$',
SchemaView.without_ui(cache_timeout=0), name='schema-json'),
path('swagger/', SchemaView.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
path('redoc/', SchemaView.with_ui('redoc', cache_timeout=0), name='schema-redoc'),
] + router.urls

View File

@ -0,0 +1,31 @@
"""Policy API Views"""
from rest_framework.serializers import ModelSerializer, SerializerMethodField
from rest_framework.viewsets import ReadOnlyModelViewSet
from passbook.core.models import Policy
from passbook.policies.forms import GENERAL_FIELDS
class PolicySerializer(ModelSerializer):
"""Policy Serializer"""
__type__ = SerializerMethodField(method_name='get_type')
def get_type(self, obj):
"""Get object type so that we know which API Endpoint to use to get the full object"""
return obj._meta.object_name.lower().replace('policy', '')
class Meta:
model = Policy
fields = ['pk'] + GENERAL_FIELDS + ['__type__']
class PolicyViewSet(ReadOnlyModelViewSet):
"""Policy Viewset"""
queryset = Policy.objects.all()
serializer_class = PolicySerializer
def get_queryset(self):
return Policy.objects.select_subclasses()

View File

@ -0,0 +1,30 @@
"""Provider API Views"""
from rest_framework.serializers import ModelSerializer, SerializerMethodField
from rest_framework.viewsets import ReadOnlyModelViewSet
from passbook.core.models import Provider
class ProviderSerializer(ModelSerializer):
"""Provider Serializer"""
__type__ = SerializerMethodField(method_name='get_type')
def get_type(self, obj):
"""Get object type so that we know which API Endpoint to use to get the full object"""
return obj._meta.object_name.lower().replace('provider', '')
class Meta:
model = Provider
fields = ['pk', 'property_mappings', '__type__']
class ProviderViewSet(ReadOnlyModelViewSet):
"""Provider Viewset"""
queryset = Provider.objects.all()
serializer_class = ProviderSerializer
def get_queryset(self):
return Provider.objects.select_subclasses()

View File

@ -0,0 +1,31 @@
"""Source API Views"""
from rest_framework.serializers import ModelSerializer, SerializerMethodField
from rest_framework.viewsets import ReadOnlyModelViewSet
from passbook.admin.forms.source import SOURCE_SERIALIZER_FIELDS
from passbook.core.models import Source
class SourceSerializer(ModelSerializer):
"""Source Serializer"""
__type__ = SerializerMethodField(method_name='get_type')
def get_type(self, obj):
"""Get object type so that we know which API Endpoint to use to get the full object"""
return obj._meta.object_name.lower().replace('source', '')
class Meta:
model = Source
fields = SOURCE_SERIALIZER_FIELDS + ['__type__']
class SourceViewSet(ReadOnlyModelViewSet):
"""Source Viewset"""
queryset = Source.objects.all()
serializer_class = SourceSerializer
def get_queryset(self):
return Source.objects.select_subclasses()

View File

@ -33,15 +33,15 @@ class PolicyEngine:
use_cache: bool = True use_cache: bool = True
policies: List[Policy] = [] policies: List[Policy] = []
__request: HttpRequest request: PolicyRequest
__user: User
__processes: List[PolicyProcessInfo] = [] __processes: List[PolicyProcessInfo] = []
def __init__(self, policies, user: User = None, request: HttpRequest = None): def __init__(self, policies, user: User, request: HttpRequest = None):
self.policies = policies self.policies = policies
self.__request = request self.request = PolicyRequest(user)
self.__user = user if request:
self.request.http_request = request
self.__processes = [] self.__processes = []
def _select_subclasses(self) -> List[Policy]: def _select_subclasses(self) -> List[Policy]:
@ -53,20 +53,16 @@ class PolicyEngine:
def build(self) -> 'PolicyEngine': def build(self) -> 'PolicyEngine':
"""Build task group""" """Build task group"""
if not self.__user:
raise ValueError("User not set.")
cached_policies = [] cached_policies = []
request = PolicyRequest(self.__user)
request.http_request = self.__request
for policy in self._select_subclasses(): for policy in self._select_subclasses():
cached_policy = cache.get(cache_key(policy, self.__user), None) cached_policy = cache.get(cache_key(policy, self.request.user), None)
if cached_policy and self.use_cache: if cached_policy and self.use_cache:
LOGGER.debug("Taking result from cache", policy=policy) LOGGER.debug("Taking result from cache", policy=policy)
cached_policies.append(cached_policy) cached_policies.append(cached_policy)
else: else:
LOGGER.debug("Evaluating policy", policy=policy) LOGGER.debug("Evaluating policy", policy=policy)
our_end, task_end = Pipe(False) our_end, task_end = Pipe(False)
task = PolicyProcess(policy, request, task_end) task = PolicyProcess(policy, self.request, task_end)
LOGGER.debug("Starting Process", policy=policy) LOGGER.debug("Starting Process", policy=policy)
task.start() task.start()
self.__processes.append(PolicyProcessInfo(process=task, self.__processes.append(PolicyProcessInfo(process=task,

View File

@ -0,0 +1,21 @@
"""Source API Views"""
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet
from passbook.policies.expiry.models import PasswordExpiryPolicy
from passbook.policies.forms import GENERAL_SERIALIZER_FIELDS
class PasswordExpiryPolicySerializer(ModelSerializer):
"""Password Expiry Policy Serializer"""
class Meta:
model = PasswordExpiryPolicy
fields = GENERAL_SERIALIZER_FIELDS + ['days', 'deny_only']
class PasswordExpiryPolicyViewSet(ModelViewSet):
"""Source Viewset"""
queryset = PasswordExpiryPolicy.objects.all()
serializer_class = PasswordExpiryPolicySerializer

View File

@ -1,3 +1,4 @@
"""General fields""" """General fields"""
GENERAL_FIELDS = ['name', 'negate', 'order', 'timeout'] GENERAL_FIELDS = ['name', 'negate', 'order', 'timeout']
GENERAL_SERIALIZER_FIELDS = ['pk', 'name', 'negate', 'order', 'timeout']

View File

@ -0,0 +1,21 @@
"""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

View File

@ -0,0 +1,21 @@
"""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.hibp.models import HaveIBeenPwendPolicy
class HaveIBeenPwendPolicySerializer(ModelSerializer):
"""Have I Been Pwned Policy Serializer"""
class Meta:
model = HaveIBeenPwendPolicy
fields = GENERAL_SERIALIZER_FIELDS + ['allowed_count']
class HaveIBeenPwendPolicyViewSet(ModelViewSet):
"""Source Viewset"""
queryset = HaveIBeenPwendPolicy.objects.all()
serializer_class = HaveIBeenPwendPolicySerializer

View File

@ -0,0 +1,21 @@
"""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

View File

@ -0,0 +1,23 @@
"""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.password.models import PasswordPolicy
class PasswordPolicySerializer(ModelSerializer):
"""Password Policy Serializer"""
class Meta:
model = PasswordPolicy
fields = GENERAL_SERIALIZER_FIELDS + ['amount_uppercase', 'amount_lowercase',
'amount_symbols', 'length_min', 'symbol_charset',
'error_message']
class PasswordPolicyViewSet(ModelViewSet):
"""Source Viewset"""
queryset = PasswordPolicy.objects.all()
serializer_class = PasswordPolicySerializer

View File

@ -0,0 +1,21 @@
"""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.reputation.models import ReputationPolicy
class ReputationPolicySerializer(ModelSerializer):
"""Reputation Policy Serializer"""
class Meta:
model = ReputationPolicy
fields = GENERAL_SERIALIZER_FIELDS + ['check_ip', 'check_username', 'threshold']
class ReputationPolicyViewSet(ModelViewSet):
"""Source Viewset"""
queryset = ReputationPolicy.objects.all()
serializer_class = ReputationPolicySerializer

View File

@ -0,0 +1,21 @@
"""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

View File

@ -3,6 +3,7 @@ from __future__ import annotations
from typing import TYPE_CHECKING, List from typing import TYPE_CHECKING, List
from django.db.models import Model
from django.http import HttpRequest from django.http import HttpRequest
if TYPE_CHECKING: if TYPE_CHECKING:
@ -13,6 +14,7 @@ class PolicyRequest:
user: User user: User
http_request: HttpRequest http_request: HttpRequest
obj: Model
def __init__(self, user: User): def __init__(self, user: User):
self.user = user self.user = user

View File

@ -34,11 +34,6 @@ class PolicyTestEngine(TestCase):
engine = PolicyEngine([], self.user) engine = PolicyEngine([], self.user)
self.assertEqual(engine.build().passing, True) self.assertEqual(engine.build().passing, True)
def test_engine_without_user(self):
"""Ensure engine raises error if no user is set"""
with self.assertRaises(ValueError):
PolicyEngine([]).build()
def test_engine(self): def test_engine(self):
"""Ensure all policies passes (Mix of false and true -> false)""" """Ensure all policies passes (Mix of false and true -> false)"""
engine = PolicyEngine(DebugPolicy.objects.filter(negate__exact=False), self.user) engine = PolicyEngine(DebugPolicy.objects.filter(negate__exact=False), self.user)

View File

@ -0,0 +1,22 @@
"""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.webhook.models import WebhookPolicy
class WebhookPolicySerializer(ModelSerializer):
"""Webhook Policy Serializer"""
class Meta:
model = WebhookPolicy
fields = GENERAL_SERIALIZER_FIELDS + ['url', 'method', 'json_body', 'json_headers',
'result_jsonpath', 'result_json_value', ]
class WebhookPolicyViewSet(ModelViewSet):
"""Source Viewset"""
queryset = WebhookPolicy.objects.all()
serializer_class = WebhookPolicySerializer

View File

@ -0,0 +1,21 @@
"""ApplicationGatewayProvider API Views"""
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet
from passbook.providers.app_gw.models import ApplicationGatewayProvider
class ApplicationGatewayProviderSerializer(ModelSerializer):
"""ApplicationGatewayProvider Serializer"""
class Meta:
model = ApplicationGatewayProvider
fields = ['pk', 'server_name', 'upstream', 'enabled', 'authentication_header',
'default_content_type', 'upstream_ssl_verification', 'property_mappings']
class ApplicationGatewayProviderViewSet(ModelViewSet):
"""ApplicationGatewayProvider Viewset"""
queryset = ApplicationGatewayProvider.objects.all()
serializer_class = ApplicationGatewayProviderSerializer

View File

@ -0,0 +1,21 @@
"""OAuth2Provider API Views"""
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet
from passbook.providers.oauth.models import OAuth2Provider
class OAuth2ProviderSerializer(ModelSerializer):
"""OAuth2Provider Serializer"""
class Meta:
model = OAuth2Provider
fields = ['pk', 'name', 'redirect_uris', 'client_type',
'authorization_grant_type', 'client_id', 'client_secret', ]
class OAuth2ProviderViewSet(ModelViewSet):
"""OAuth2Provider Viewset"""
queryset = OAuth2Provider.objects.all()
serializer_class = OAuth2ProviderSerializer

View File

@ -0,0 +1,22 @@
"""OpenIDProvider API Views"""
from oidc_provider.models import Client
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet
# from passbook.providers.oidc.models import OpenIDProvider
class OpenIDProviderSerializer(ModelSerializer):
"""OpenIDProvider Serializer"""
class Meta:
model = Client
fields = ['pk', 'name', 'client_type', 'client_id', 'client_secret', 'response_types',
'jwt_alg', 'reuse_consent', 'require_consent', '_redirect_uris', '_scope']
class OpenIDProviderViewSet(ModelViewSet):
"""OpenIDProvider Viewset"""
queryset = Client.objects.all()
serializer_class = OpenIDProviderSerializer

View File

@ -0,0 +1,38 @@
"""SAMLProvider API Views"""
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet
from passbook.providers.saml.models import SAMLPropertyMapping, SAMLProvider
class SAMLProviderSerializer(ModelSerializer):
"""SAMLProvider Serializer"""
class Meta:
model = SAMLProvider
fields = ['pk', 'name', 'property_mappings', 'acs_url', 'audience', 'processor_path',
'issuer', 'assertion_valid_for', 'signing', 'signing_cert', 'signing_key', ]
class SAMLProviderViewSet(ModelViewSet):
"""SAMLProvider Viewset"""
queryset = SAMLProvider.objects.all()
serializer_class = SAMLProviderSerializer
class SAMLPropertyMappingSerializer(ModelSerializer):
"""SAMLPropertyMapping Serializer"""
class Meta:
model = SAMLPropertyMapping
fields = ['pk', 'name', 'saml_name', 'friendly_name', 'values']
class SAMLPropertyMappingViewSet(ModelViewSet):
"""SAMLPropertyMapping Viewset"""
queryset = SAMLPropertyMapping.objects.all()
serializer_class = SAMLPropertyMappingSerializer

View File

@ -104,12 +104,33 @@ INSTALLED_APPS = [
GUARDIAN_MONKEY_PATCH = False GUARDIAN_MONKEY_PATCH = False
SWAGGER_SETTINGS = {
'DEFAULT_INFO': 'passbook.api.v2.urls.info',
# 'SECURITY_DEFINITIONS': {
# 'JWT': {
# 'type': 'apiKey',
# 'name': 'Authorization',
# 'in': 'header'
# }
# }
}
REST_FRAMEWORK = { REST_FRAMEWORK = {
# Use Django's standard `django.contrib.auth` permissions, 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
# or allow read-only access for unauthenticated users. 'PAGE_SIZE': 100,
'DEFAULT_PERMISSION_CLASSES': [ 'DEFAULT_FILTER_BACKENDS': [
'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly' 'django_filters.rest_framework.DjangoFilterBackend',
] 'rest_framework.filters.OrderingFilter',
'rest_framework.filters.SearchFilter',
],
'DEFAULT_PERMISSION_CLASSES': (
# 'rest_framework.permissions.IsAuthenticated',
'passbook.api.permissions.CustomObjectPermissions',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication',
# 'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
),
} }
CACHES = { CACHES = {

View File

@ -0,0 +1,39 @@
"""Source API Views"""
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet
from passbook.admin.forms.source import SOURCE_SERIALIZER_FIELDS
from passbook.sources.ldap.models import LDAPSource
class LDAPSourceSerializer(ModelSerializer):
"""LDAP Source Serializer"""
class Meta:
model = LDAPSource
fields = SOURCE_SERIALIZER_FIELDS + [
'server_uri',
'bind_cn',
'bind_password',
'start_tls',
'base_dn',
'additional_user_dn',
'additional_group_dn',
'user_object_filter',
'group_object_filter',
'user_group_membership_field',
'object_uniqueness_field',
'sync_groups',
'sync_parent_group',
'property_mappings',
]
extra_kwargs = {
'password': {'bind_password': True}
}
class LDAPSourceViewSet(ModelViewSet):
"""Source Viewset"""
queryset = LDAPSource.objects.all()
serializer_class = LDAPSourceSerializer

View File

@ -0,0 +1,23 @@
"""OAuth Source Serializer"""
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet
from passbook.admin.forms.source import SOURCE_SERIALIZER_FIELDS
from passbook.sources.oauth.models import OAuthSource
class OAuthSourceSerializer(ModelSerializer):
"""OAuth Source Serializer"""
class Meta:
model = OAuthSource
fields = SOURCE_SERIALIZER_FIELDS + ['provider_type', 'request_token_url',
'authorization_url', 'access_token_url',
'profile_url', 'consumer_key', 'consumer_secret']
class OAuthSourceViewSet(ModelViewSet):
"""Source Viewset"""
queryset = OAuthSource.objects.all()
serializer_class = OAuthSourceSerializer