Compare commits

..

255 Commits

Author SHA1 Message Date
Langhammer, Jens
34cbf5f702 new release: 0.5.0-beta 2019-10-04 13:55:13 +02:00
Langhammer, Jens
3c6e94b6a8 ci(minor): fix path in bumpversion config 2019-10-04 13:55:12 +02:00
Langhammer, Jens
1cd149c815 policy(minor): fix linting 2019-10-04 13:49:27 +02:00
Langhammer, Jens
4c6f562805 policy(minor): fix deadlock issue 2019-10-04 13:44:26 +02:00
Langhammer, Jens
e59c4ec1c7 root(minor): cleanup, remove unused log 2019-10-04 13:43:47 +02:00
Langhammer, Jens
1169db7530 docker(minor): move docker-related files into separate folder 2019-10-04 12:45:19 +02:00
Langhammer, Jens
1453008796 wsgi(minor): add proper request logging 2019-10-04 12:44:59 +02:00
Langhammer, Jens
2209b6d603 deploy(minor): fix robots.txt not being in the right path
fix path matching in docker compose
2019-10-04 12:01:38 +02:00
Langhammer, Jens
ccbc0384f9 deploy(minor): remove app-gw, add robots.txt 2019-10-04 11:57:41 +02:00
Langhammer, Jens
a48924c896 docker(minor): switch to debian based image so we can use wheels 2019-10-04 11:50:52 +02:00
Langhammer, Jens
dc8d8dd2b6 deploy(minor): add docker-compose file for easy testing 2019-10-04 11:50:26 +02:00
Langhammer, Jens
afca94ceb8 policy(minor): improve loading of policy subclasses 2019-10-04 10:22:06 +02:00
Langhammer, Jens
0b86231a36 *(minor): make better use of structured logging 2019-10-04 10:21:33 +02:00
Langhammer, Jens
c0df1f38b8 *(minor): remove __name__ param from get_logger 2019-10-04 10:08:53 +02:00
Langhammer, Jens
2b8fed8f4e saml_idp(minor): rewrite to use defusedxml instead of bs4 2019-10-04 09:50:25 +02:00
Langhammer, Jens
c7322a32a0 app_gw(minor): remove current implementation 2019-10-04 09:28:28 +02:00
Jens Langhammer
64b75cab84 policy(minor): add data class for policy request 2019-10-03 10:45:31 +02:00
Jens Langhammer
f58bc61999 new release: 0.4.2-beta 2019-10-02 21:05:51 +00:00
Jens Langhammer
fb8ccc0283 lint(minor): fix import order 2019-10-02 21:05:37 +00:00
Jens Langhammer
c38012f147 new release: 0.4.1-beta 2019-10-02 21:04:16 +00:00
Jens Langhammer
3676ff21c2 helm(minor): use postgres 4.2.2 2019-10-02 21:03:39 +00:00
Jens Langhammer
920e705d75 policy(minor): lookup correct policy subclass 2019-10-02 22:28:58 +02:00
Jens Langhammer
de0b137b1e policy(minor): improve error handling 2019-10-02 22:28:39 +02:00
Jens Langhammer
d44ac6e2a3 static(minor): fix build path for static image 2019-10-02 22:16:48 +02:00
Jens Langhammer
71039a4012 helm(minor): fix p2 to passbook 2019-10-02 22:16:32 +02:00
Langhammer, Jens
8745ac7932 new release: 0.4.0-beta 2019-10-01 17:01:30 +02:00
Langhammer, Jens
7f70048423 ci(minor): disable pylint since its currently broken upstream 2019-10-01 16:53:09 +02:00
Langhammer, Jens
97dbfc8885 req(minor): fix dependency issue by downgrading prospector 2019-10-01 15:54:29 +02:00
Langhammer, Jens
149ea22a93 k8s(minor): switch to uwsgi 2019-10-01 15:43:06 +02:00
Langhammer, Jens
404ed5406d k8s(minor): remove passwords from configmap 2019-10-01 15:42:55 +02:00
Langhammer, Jens
b8656858ec k8s(minor): load secrets as env vars 2019-10-01 15:42:14 +02:00
Langhammer, Jens
6b0f0e8993 deploy(minor): use 5.x postgresql chart for psql 10.x 2019-10-01 15:33:43 +02:00
Langhammer, Jens
aec1ccd88d root(minor): fix redis password not being loaded 2019-10-01 15:30:35 +02:00
Langhammer, Jens
bee5c200b6 docker(minor): fix static build failing 2019-10-01 15:30:22 +02:00
Langhammer, Jens
9d640efc88 new release: 0.3.0-beta 2019-10-01 13:50:50 +02:00
Langhammer, Jens
f0907841dd docker(minor): remove virtualenv from pipenv 2019-10-01 13:50:37 +02:00
Langhammer, Jens
2bffc12ef9 ci(minor): fix default settings so CI works 2019-10-01 13:22:38 +02:00
Langhammer, Jens
2ff9ec6522 ci(minor): fix not all packages being installed 2019-10-01 11:34:34 +02:00
Langhammer, Jens
43a54f5c54 ci(minor): install pipenv before testing 2019-10-01 11:12:59 +02:00
Langhammer, Jens
7bff2734aa lint(minor): fix all remaining pylint and prospector errors 2019-10-01 11:08:56 +02:00
Langhammer, Jens
84768c0ec6 helm(minor): remove rabbitmq 2019-10-01 10:48:55 +02:00
Langhammer, Jens
f4499a5459 *(minor): stdlib logging to structlog 2019-10-01 10:24:10 +02:00
Langhammer, Jens
b3aede5bba policy(minor): Move policy-related code to separate package 2019-10-01 10:17:39 +02:00
Langhammer, Jens
531ea1c039 build(minor): rename dockerfiles to be detected correctly 2019-09-30 18:05:42 +02:00
Langhammer, Jens
c2c5ff6912 config(minor): CONFIG.get -> CONFIG.y 2019-09-30 18:04:04 +02:00
Langhammer, Jens
9cddab8fd5 deploy(minor): switch to pipfile 2019-09-10 17:00:13 +02:00
Langhammer, Jens
06d15d8a27 new release: 0.2.8-beta 2019-07-22 17:18:07 +02:00
Langhammer, Jens
b5c711854b deploy: fix static deployment and static container 2019-07-22 17:17:53 +02:00
Langhammer, Jens
4cf6c36f34 new release: 0.2.7-beta 2019-07-22 15:54:34 +02:00
Langhammer, Jens
75a6f6c875 deploy: remove old files from bumpversion 2019-07-22 15:54:10 +02:00
Langhammer, Jens
62abe3f256 suspicious_policy: fix Request IP lookup 2019-07-22 15:46:41 +02:00
Langhammer, Jens
9296c41650 ci: add missing packaging dependency 2019-07-22 15:35:11 +02:00
Langhammer, Jens
7fb48fde6d deploy: add static deployment, add resource reservations/limits 2019-07-22 15:22:10 +02:00
Langhammer, Jens
174472bb45 all: get rid of individual requirements file, remove version from every module 2019-07-22 15:20:17 +02:00
Langhammer, Jens
17575ed921 deploy: rewrite docker files to be more stackable 2019-07-22 15:18:33 +02:00
Langhammer, Jens
b1b1a27444 client-packages: now deprecated 2019-07-22 15:17:58 +02:00
Jens Langhammer
f97a5eeefb api: *actually* fix drf dependency issue 2019-07-15 15:05:54 +00:00
Jens Langhammer
10fd96981e new release: 0.2.6-beta 2019-07-15 13:42:18 +00:00
Jens Langhammer
67e3eb549c api: fix wrong django-rest-framework dependency 2019-07-15 13:42:03 +00:00
Jens Langhammer
30a6d1f0b1 new release: 0.2.5-beta 2019-07-15 13:31:04 +00:00
Langhammer, Jens
3d1fa9f048 app_gw: Rewrite redirect responses (replace upstream location with server_name) 2019-07-09 15:28:52 +02:00
Jens Langhammer
1d2be6e68b root: fix sentry sending wrong release 2019-07-05 16:00:01 +02:00
Jens Langhammer
c21e343986 oidc_provider: fix error when creating a new provider 2019-07-05 15:59:52 +02:00
Jens Langhammer
ff37ed095c new release: 0.2.4-beta 2019-07-05 15:30:13 +02:00
Jens Langhammer
8623a2c3fc oidc_provider: fix error trying to create RSA Key before migrations are run 2019-07-05 15:27:04 +02:00
Jens Langhammer
23d277eaf1 remove oidc from OAuth2, add dedicated OIDC provider 2019-07-05 15:21:48 +02:00
Jens Langhammer
75ced59451 helm: fix syntax error 2019-07-05 15:21:12 +02:00
Jens Langhammer
bccf424c5e new release: 0.2.3-beta 2019-07-04 16:25:33 +02:00
Jens Langhammer
2f9ae40d20 client-sentry: fix 400 failing upload 2019-07-04 16:25:17 +02:00
Jens Langhammer
11e1eec3fb ci: fix new dependencies not being installed on the fly 2019-07-04 16:21:35 +02:00
Jens Langhammer
765c5633df helm: add appgw to ingress 2019-07-04 16:07:16 +02:00
Jens Langhammer
6344b1aafb helm: add deployment for appgw 2019-07-04 15:25:36 +02:00
Jens Langhammer
ed25801e6e core: revert to cherrypy for main webserver and use daphne only for app_gw 2019-07-04 15:23:05 +02:00
Jens Langhammer
4d0148193f root: migrate to new sentry instance 2019-07-03 17:35:54 +02:00
Jens Langhammer
804ae15c2e new release: 0.2.2-beta 2019-06-25 18:50:41 +02:00
Jens Langhammer
b35a9fad86 Fix linting errors with current build-base image 2019-06-25 18:50:37 +02:00
Jens Langhammer
a4f83bd28a new release: 0.2.1-beta 2019-06-25 18:25:27 +02:00
Jens Langhammer
796f83c3d0 Fix requirements file importing wrong path 2019-06-25 18:24:07 +02:00
Jens Langhammer
2099bbb713 new release: 0.2.0-beta 2019-06-25 18:16:14 +02:00
Jens Langhammer
67beba8f78 Fix wrong URLConf being loaded 2019-06-25 18:11:08 +02:00
Jens Langhammer
a798412e17 separate passbook.core into passbook.root and passbook.core
Move Main Django Project into passbook.root while passbook.core holds core functionality.

passbook.root contains main settings, ASGI & WSGI, celery and URLs.
2019-06-25 18:00:54 +02:00
Jens Langhammer
3b2c2d781f Fix typo 2019-06-25 17:59:51 +02:00
Jens Langhammer
98c844f3d6 improve OIDC compatibility 2019-06-25 17:57:25 +02:00
Jens Langhammer
2645bd0132 new release: 0.1.38-beta 2019-04-29 23:26:18 +02:00
Jens Langhammer
2c4fc56b49 Merge branch '27-rewrite-oauth-client-as-factor' into 'master'
Resolve "Rewrite OAuth Client as Factor"

Closes #27

See merge request BeryJu.org/passbook!14
2019-04-29 21:25:04 +00:00
Jens Langhammer
0ec1468058 remove unused import 2019-04-29 23:22:54 +02:00
Jens Langhammer
5d1a3043b2 create SSOLoginPolicy, which allows factors to be applied when user comes from SSO login
implement SESSIION_IS_SSO_LOGIN for OAuth Client and core MFA
2019-04-29 23:19:37 +02:00
Jens Langhammer
b46958d1f9 send session to task 2019-04-29 23:18:51 +02:00
Jens Langhammer
5daa8d5fe3 fix missing/wrong widget inputs 2019-04-29 23:16:04 +02:00
Jens Langhammer
31846f1d05 Show redirect URL in <pre> element 2019-04-29 22:32:22 +02:00
Jens Langhammer
1fac964b8b increase application close timeout 2019-04-29 22:19:26 +02:00
Jens Langhammer
dfa6ed8ac2 add help to show how SAML Property Mapping substitutes variables 2019-04-29 22:19:13 +02:00
Jens Langhammer
66fe10299e new release: 0.1.37-beta 2019-04-29 21:43:18 +02:00
Jens Langhammer
e0a3ec033f fix IDP-Initiated SAML Login 2019-04-29 21:39:41 +02:00
Jens Langhammer
7033ec0ab9 remove debug print 2019-04-29 21:39:30 +02:00
Jens Langhammer
4004579905 remove nexus_upload command 2019-04-29 21:39:16 +02:00
Jens Langhammer
9fe9e48a5c new release: 0.1.36-beta 2019-04-29 20:57:57 +02:00
Jens Langhammer
595a6c7fe6 remove guardian completely 2019-04-29 20:57:54 +02:00
Jens Langhammer
11b5860d4a new release: 0.1.35-beta 2019-04-29 20:47:32 +02:00
Jens Langhammer
9bdbff4cda fix gitlab-ci using incorrect variables for docker access 2019-04-29 20:42:24 +02:00
Jens Langhammer
e0d597eeac show cache on admin overview, add modal to clear cache, re-add logging to policy 2019-04-29 20:37:44 +02:00
Jens Langhammer
f576985cc9 remove django guardian and check application access via PolicyEngine 2019-04-29 20:07:18 +02:00
Jens Langhammer
22a6aef60b fix wrong import 2019-04-29 20:06:52 +02:00
Jens Langhammer
ec0a6e7854 new release: 0.1.34-beta 2019-04-29 19:22:20 +02:00
Jens Langhammer
6904608e6f fix clicking on administration always loading admin interface 2019-04-29 19:22:14 +02:00
Jens Langhammer
cb3732cb2b filter out connection errors for sentry 2019-04-29 19:16:49 +02:00
Jens Langhammer
57de6cbafc repo cleanup, switch to new docker registry 2019-04-29 17:05:39 +02:00
Jens Langhammer
b1dda764a9 Merge branch 'master' of git.beryju.org:BeryJu.org/passbook
# Conflicts:
#	debian/etc/passbook/config.yml
#	helm/passbook/templates/passbook-configmap.yaml
2019-04-18 11:34:13 +02:00
Jens Langhammer
5ec2102487 Merge branch '39-saml-audience-as-database-field' into 'master'
Resolve "SAML: Audience as Database field"

Closes #39

See merge request BeryJu.org/passbook!25
2019-04-18 09:31:56 +00:00
Jens Langhammer
9f8fb7378a add audience field, switch base processor, better handle processor loading failure 2019-04-18 11:30:21 +02:00
Jens Langhammer
98cd646044 remove unneeded processors 2019-04-18 11:09:12 +02:00
Jens Langhammer
0cba1b4c45 fix SAML RancherProcessor not being loaded by default 2019-04-18 11:01:44 +02:00
Jens Langhammer
53918462b6 new release: 0.1.33-beta 2019-04-18 10:28:12 +02:00
Jens Langhammer
8a7e74b523 better release commit messages 2019-04-18 10:28:09 +02:00
Jens Langhammer
4dc7065e97 prepare 0.1.33 2019-04-18 10:25:22 +02:00
Jens Langhammer
3c93bb9f9f remove included CI file 2019-04-18 10:18:47 +02:00
Jens Langhammer
8143fae2d6 switch to custom CI base image with dependencies installed 2019-04-18 10:15:44 +02:00
Jens Langhammer
3cfe45d3cb fix broken icon for helm chart 2019-04-17 17:53:56 +02:00
Jens Langhammer
8e5c3f2f31 remove unused import 2019-04-17 17:53:45 +02:00
Jens Langhammer
5a3b2fdd49 add Rancher SAML processor 2019-04-17 17:53:15 +02:00
Jens Langhammer
e47b9f0d57 fix SAML Request not being parsed all the time 2019-04-17 17:53:05 +02:00
Jens Langhammer
146dd747f1 fix EntityID being None in SAML Metadata 2019-04-17 17:52:24 +02:00
Jens Langhammer
f2ce56063b bump version: 0.1.31-beta -> 0.1.32-beta 2019-04-17 14:27:41 +02:00
Jens Langhammer
b26f378e4c prepare 0.1.32 2019-04-17 14:27:03 +02:00
Jens Langhammer
9072b836c6 automatically add response_type if not given in OAuth Request 2019-04-17 14:25:51 +02:00
Jens Langhammer
2fa57d064e bump version: 0.1.30-beta -> 0.1.31-beta 2019-04-13 17:58:09 +02:00
Jens Langhammer
146705c60a prepare 0.1.31-beta 2019-04-13 17:58:03 +02:00
Jens Langhammer
5029a99df6 Merge branch '37-guardian' into 'master'
Resolve "Guardian"

Closes #37

See merge request BeryJu.org/passbook!23
2019-04-13 15:56:54 +00:00
Jens Langhammer
e7129d18f6 fix inconsistent migrations 2019-04-13 17:52:11 +02:00
Jens Langhammer
d2bf9f81d6 remove raven middleware 2019-04-13 17:46:51 +02:00
Jens Langhammer
30acf0660b Merge branch 'master' into 37-guardian 2019-04-13 17:43:02 +02:00
Jens Langhammer
dda41af5c8 remove logging to increase speed, add more caching to policy and rewriter 2019-04-13 17:22:03 +02:00
Jens Langhammer
9b5b03647b move actual proxying logic to separate class 2019-04-13 16:05:11 +02:00
Jens Langhammer
940b3eb943 move logging to separate thread 2019-04-13 16:04:48 +02:00
Jens Langhammer
16eb629b71 only enable sentry when not DEBUG 2019-04-11 15:30:42 +02:00
Jens Langhammer
755045b226 try to fix app_gw being null 2019-04-11 15:30:07 +02:00
Jens Langhammer
61478db94e use global urllib Pools 2019-04-11 15:29:35 +02:00
Jens Langhammer
f69f959bdb allow setting authentication_header to empty string (disabling the header) 2019-04-11 15:29:01 +02:00
Jens Langhammer
146edb45d4 bump version: 0.1.29-beta -> 0.1.30-beta 2019-04-11 14:22:34 +02:00
Jens Langhammer
045a802365 don't use context manager in web command 2019-04-11 14:22:32 +02:00
Jens Langhammer
c90d8ddcff bump version: 0.1.28-beta -> 0.1.29-beta 2019-04-11 14:03:08 +02:00
Jens Langhammer
3ff2ec929f prepare 0.1.29 2019-04-11 14:03:05 +02:00
Jens Langhammer
a3ef26b7ad Run collectstatic before coverage, use autoreload on celery worker 2019-04-11 13:54:11 +02:00
Jens Langhammer
19cd1624c1 replace cherrypy with daphne 2019-04-11 13:43:49 +02:00
Jens Langhammer
366ef352c6 switch to whitenoise for static files 2019-04-11 13:43:08 +02:00
Jens Langhammer
a9031a6abc Add libpq-dev dependency so psycopg2 build works 2019-04-11 12:44:26 +02:00
Jens Langhammer
a1a5223b58 bump version: 0.1.27-beta -> 0.1.28-beta 2019-04-11 10:48:31 +02:00
Jens Langhammer
c723b0233f prepare 0.1.28 2019-04-11 10:48:28 +02:00
Jens Langhammer
b369eb28f1 set default log level to warn, fix clean_nonces not working 2019-04-11 10:43:13 +02:00
Jens Langhammer
9b8f390e31 Merge branch '38-websocket-proxying' into 'master'
Resolve "Websocket Proxying"

Closes #38

See merge request BeryJu.org/passbook!24
2019-04-10 20:42:24 +00:00
Jens Langhammer
11630c9a74 switch kubernetes deployment to daphne server 2019-04-10 22:38:25 +02:00
Jens Langhammer
c9ac10f6f6 Implement websocket proxy 2019-04-10 19:03:42 +02:00
Jens Langhammer
04d613cb28 Move code from django-revproxy to app_gw to fix cookie bug 2019-04-10 19:03:22 +02:00
Jens Langhammer
40866f9ecd Choose upstream more cleverly 2019-04-10 18:49:33 +02:00
Jens Langhammer
d8585eb872 trigger autoreload from config files 2019-04-10 18:48:55 +02:00
Jens Langhammer
15aaeda475 remove unused import 2019-04-10 18:47:21 +02:00
Jens Langhammer
8536ef9e23 Add guardian for Application permissions 2019-04-10 18:46:33 +02:00
Jens Langhammer
35b6bb6b3f fix failing CI 2019-04-09 17:26:53 +02:00
Jens Langhammer
eaa573c715 fully remove raven and switch WSGI and logging to sentry_sdk 2019-04-05 16:11:53 +02:00
Jens Langhammer
660972e303 add ability to have non-expiring nonces, clean up expired nonces 2019-04-04 21:49:10 +02:00
Jens Langhammer
a21012bf0c switch from raven to sentry_sdk 2019-04-04 21:48:50 +02:00
Jens Langhammer
8dbafa4bda fix allauth client's formatting 2019-04-04 21:47:28 +02:00
Jens Langhammer
80049413f0 bump version: 0.1.26-beta -> 0.1.27-beta 2019-03-22 14:51:13 +01:00
Jens Langhammer
2739442d4a prepare 0.1.27 2019-03-22 14:51:09 +01:00
Jens Langhammer
c679f0a67c bump version: 0.1.25-beta -> 0.1.26-beta 2019-03-22 12:48:00 +01:00
Jens Langhammer
d9a952dd03 prepare 0.1.26 2019-03-22 12:47:57 +01:00
Jens Langhammer
9a1a0f0aa8 Merge branch '35-better-error-templates' into 'master'
Resolve "Better Error templates"

Closes #35

See merge request BeryJu.org/passbook!20
2019-03-22 11:19:42 +00:00
Jens Langhammer
4d6bb60134 add custom template views 2019-03-22 12:16:30 +01:00
Jens Langhammer
80e6d59382 Merge branch '34-parsed-url-cached' into 'master'
Resolve "InvalidUpstream: Upstream URL scheme must be either 'http' or 'https' (https://ory1-esxi-prod-1.ory1.beryju.org)."

Closes #34

See merge request BeryJu.org/passbook!19
2019-03-22 09:58:44 +00:00
Jens Langhammer
81ac951872 validate upstream in form 2019-03-22 10:55:26 +01:00
Jens Langhammer
f33e553cfd always parse url instead of once 2019-03-22 10:55:04 +01:00
Jens Langhammer
9b0240dc26 bump version: 0.1.24-beta -> 0.1.25-beta 2019-03-21 16:50:00 +01:00
Jens Langhammer
c327310392 prepare 0.1.24-beta release 2019-03-21 16:49:57 +01:00
Jens Langhammer
457375287c Merge branch '30-application-security-gateway' into 'master'
Resolve "Application Security Gateway (Reverse Proxy)"

Closes #30

See merge request BeryJu.org/passbook!17
2019-03-21 15:41:34 +00:00
Jens Langhammer
7e87bfef5b validate server_name in form 2019-03-21 16:36:38 +01:00
Jens Langhammer
a7af5268de Invalidate cache when ApplicationGateway instance is saved 2019-03-21 16:27:37 +01:00
Jens Langhammer
6d916029bb implement actual Rewriting logic 2019-03-21 16:22:07 +01:00
Jens Langhammer
81fdcbadad add compiled regex to RewriteRule 2019-03-21 16:21:51 +01:00
Jens Langhammer
ec1e25fe71 cleanup property_mapping list 2019-03-21 16:21:11 +01:00
Jens Langhammer
b5306e4a94 Redirect to login on reverse proxy 2019-03-21 15:15:01 +01:00
Jens Langhammer
801b8a1e59 prevent ZeroDivisionError 2019-03-21 15:05:04 +01:00
Jens Langhammer
3a52059793 cleanup post-migration mess 2019-03-21 15:02:33 +01:00
Jens Langhammer
10b7d99b37 Merge branch 'master' into 30-application-security-gateway
# Conflicts:
#	passbook/core/policies.py
#	passbook/core/settings.py
2019-03-21 14:58:10 +01:00
Jens Langhammer
6be8d0cbb2 Better handle policy timeouts 2019-03-21 14:53:57 +01:00
Jens Langhammer
5b8e3689ec Check for policies in app_gw 2019-03-21 14:53:47 +01:00
Jens Langhammer
25a5d8f5da Don't use LoginRequired for PermissionDenied View 2019-03-21 14:53:38 +01:00
Jens Langhammer
883d439544 add timeout field to policy to prevent stuck policies 2019-03-21 14:48:51 +01:00
Jens Langhammer
1c3b5889e5 Merge branch '33-cache-policy-results' into 'master'
Resolve "Cache Policy Results"

Closes #33

See merge request BeryJu.org/passbook!18
2019-03-21 10:40:36 +00:00
Jens Langhammer
87012b65e1 add redis as service in CI for unittests 2019-03-21 11:35:40 +01:00
Jens Langhammer
29913773a7 invalidate cache when policy is saved 2019-03-21 11:29:11 +01:00
Jens Langhammer
0bc6a4fed4 explicitly use redis db 2019-03-21 11:28:57 +01:00
Jens Langhammer
4645d8353f utilise cache in PolicyEngine 2019-03-21 11:08:32 +01:00
Jens Langhammer
260c5555fa add redis dependency back in for caching 2019-03-21 11:08:08 +01:00
Jens Langhammer
6f7b917c38 bump version: 0.1.23-beta -> 0.1.24-beta 2019-03-20 23:00:33 +01:00
Jens Langhammer
1456ee6d3e prepare 0.1.24 2019-03-20 23:00:22 +01:00
Jens Langhammer
ae3d3d0295 fix TypeError: can only concatenate list (not "str") to list 2019-03-20 22:50:09 +01:00
Jens Langhammer
c23ceacd0b initial implementation of reverse proxy, using django-revproxy from within a middleware
add new config entry "primary_domain" which is used to set the cookie domain
2019-03-20 22:42:47 +01:00
Jens Langhammer
5155204283 Merge branch '32-automatically-set-owner-field-when-creating-oauth-provider' into 'master'
Resolve "Automatically set owner field when creating OAuth Provider"

Closes #32

See merge request BeryJu.org/passbook!16
2019-03-20 21:20:54 +00:00
Jens Langhammer
5509ec9b0f Merge branch '29-oauth-provider-add-extra-info-button-to-show-urls' into 'master'
Resolve "OAuth Provider: Add extra info button to show URLs"

Closes #29

See merge request BeryJu.org/passbook!15
2019-03-20 21:17:36 +00:00
Jens Langhammer
d6f9b2e47d remove user field from form. Closes #32 2019-03-20 20:09:27 +01:00
Jens Langhammer
67aa4aef11 add modal for OAuth Providers showing the URLs 2019-03-20 20:03:28 +01:00
Jens Langhammer
9e46c8bfec bump version: 0.1.22-beta -> 0.1.23-beta 2019-03-18 20:54:31 +01:00
Jens Langhammer
1eaa9b9733 prepare 0.1.23 2019-03-18 20:54:23 +01:00
Jens Langhammer
ee05834b69 Merge branch '28-openid-connect-discovery' into 'master'
set issuer to root address instead of well-known path

Closes #28

See merge request BeryJu.org/passbook!13
2019-03-18 19:52:13 +00:00
Jens Langhammer
fccc8f4959 set issuer to root address instead of well-known path 2019-03-18 20:42:32 +01:00
Jens Langhammer
c721620f96 Merge branch '28-openid-connect-discovery' into 'master'
Resolve "OpenID Connect Discovery support"

Closes #28

See merge request BeryJu.org/passbook!12
2019-03-18 19:42:08 +00:00
Jens Langhammer
c9f73d718e start implementing openid connect discovery 2019-03-18 20:35:11 +01:00
Jens Langhammer
bfa58be721 bump version: 0.1.21-beta -> 0.1.22-beta 2019-03-14 21:22:15 +01:00
Jens Langhammer
4bb602149e perapre 0.1.22 2019-03-14 21:20:55 +01:00
Jens Langhammer
81ab9092fc Fix OAuth Client's disconnect view having invalid URL names 2019-03-14 21:19:14 +01:00
Jens Langhammer
29d5962c4c add Azure AD Source 2019-03-14 21:18:55 +01:00
Jens Langhammer
5c75339946 point to correct icons 2019-03-14 21:18:13 +01:00
Jens Langhammer
4774d9a46c fix delete form not working 2019-03-14 21:17:41 +01:00
Jens Langhammer
dbe16ba4fd fix layout when on mobile viewport and scrolling 2019-03-14 21:17:28 +01:00
Jens Langhammer
6972cf00a0 move icons to single folder, cleanup 2019-03-14 21:17:07 +01:00
Jens Langhammer
0445be9712 fix missing debug template 2019-03-14 21:16:27 +01:00
Jens Langhammer
89dbdd9585 bump version: 0.1.20-beta -> 0.1.21-beta 2019-03-14 18:08:02 +01:00
Jens Langhammer
da88ce7150 prepare 0.1.21 2019-03-14 18:02:13 +01:00
Jens Langhammer
5f50fcfcf5 detect HTTPS from reverse proxy 2019-03-14 18:01:41 +01:00
Jens Langhammer
96be087221 add request debug view 2019-03-14 18:01:27 +01:00
Jens Langhammer
a53a269a8c bump version: 0.1.19-beta -> 0.1.20-beta 2019-03-13 16:51:43 +01:00
Jens Langhammer
59565a5286 prepare 0.1.20 2019-03-13 16:51:38 +01:00
Jens Langhammer
ae3c092238 add user settings for Sources 2019-03-13 16:49:30 +01:00
Jens Langhammer
e98e5e4e3e fix GitHub Pretend again 2019-03-13 15:52:05 +01:00
Jens Langhammer
d50c7ec8d4 bump version: 0.1.18-beta -> 0.1.19-beta 2019-03-13 15:16:48 +01:00
Jens Langhammer
c0fdf377d1 prepare 0.1.18 2019-03-13 15:14:36 +01:00
Jens Langhammer
70c11c8988 fix GitHub Pretend throwing a 500 error 2019-03-13 15:12:13 +01:00
Jens Langhammer
67b19becc1 fix API Call for sentry-client, add missing template 2019-03-13 14:27:34 +01:00
Jens Langhammer
ae64024ef4 bump version: 0.1.17-beta -> 0.1.18-beta 2019-03-13 11:31:05 +01:00
Jens Langhammer
e6571826cb adjust versions for client packages, auto build client-packages 2019-03-12 17:30:57 +01:00
Jens Langhammer
c621e61978 fix included yaml file 2019-03-12 17:19:13 +01:00
Jens Langhammer
3626fa4b98 add sentry client 2019-03-12 17:18:08 +01:00
Jens Langhammer
01b0eb159a fix Server Error when downloading metadata 2019-03-12 17:08:53 +01:00
Jens Langhammer
63aa48d981 bump version: 0.1.16-beta -> 0.1.17-beta 2019-03-12 15:55:18 +01:00
Jens Langhammer
2e0ba05d55 prepare 0.1.17 2019-03-12 15:55:14 +01:00
Jens Langhammer
b2ac57bb67 switch to vertical navigation 2019-03-12 13:35:09 +01:00
Jens Langhammer
4c22e5c2c8 don't use celery heartbeat, use TCP keepalive instead 2019-03-12 13:34:54 +01:00
Jens Langhammer
4a7b0ec8a9 remove Application.user_is_authorized 2019-03-12 10:56:01 +01:00
Jens Langhammer
330118249e bump version: 0.1.15-beta -> 0.1.16-beta 2019-03-11 21:35:11 +01:00
Jens Langhammer
8d4dabde02 finalize RabbitMQ replacement, update debian package, remove redis tgz 2019-03-11 21:35:06 +01:00
Jens Langhammer
cf7323c41b bump version: 0.1.14-beta -> 0.1.15-beta 2019-03-11 21:01:18 +01:00
Jens Langhammer
edd856df7d redis -> rabbitmq 2019-03-11 20:46:19 +01:00
Jens Langhammer
5e35859db6 bump version: 0.1.13-beta -> 0.1.14-beta 2019-03-11 11:44:34 +01:00
Jens Langhammer
acabb2df54 fix unittests 2019-03-11 11:44:12 +01:00
Jens Langhammer
e6376a05f7 bump version: 0.1.12-beta -> 0.1.13-beta 2019-03-11 11:31:12 +01:00
Jens Langhammer
1f45aff7ad prepare 0.1.13 2019-03-11 11:31:06 +01:00
Jens Langhammer
e1f1f617b6 fix UserChangePasswordView not requiring Login 2019-03-11 11:25:59 +01:00
Jens Langhammer
2690675dca allow custom email server for helm installs 2019-03-11 11:03:25 +01:00
Jens Langhammer
7529b51358 Fix DoesNotExist error when running PolicyEngine against None user 2019-03-11 10:52:50 +01:00
Jens Langhammer
c394066d99 bump version: 0.1.11-beta -> 0.1.12-beta 2019-03-11 09:51:00 +01:00
Jens Langhammer
9c585032ef prepare 0.1.12-beta 2019-03-11 09:50:57 +01:00
Jens Langhammer
d408031304 fix OAuth Authorization View not requiring authentication 2019-03-11 09:48:36 +01:00
Jens Langhammer
c47bc11ec0 disable automatic k8s deployment for now 2019-03-11 09:47:06 +01:00
Jens Langhammer
1deb094afe install updated helm release from local folder 2019-03-10 21:47:22 +01:00
Jens Langhammer
501fed1922 rewrite PasswordFactor to use backends setting instead of trying all backends 2019-03-10 21:47:08 +01:00
270 changed files with 4142 additions and 1975 deletions

View File

@@ -1,10 +1,10 @@
[bumpversion]
current_version = 0.1.11-beta
current_version = 0.5.0-beta
tag = True
commit = True
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\-(?P<release>.*)
serialize = {major}.{minor}.{patch}-{release}
message = bump version: {current_version} -> {new_version}
message = new release: {new_version}
tag_name = version/{new_version}
[bumpversion:part:release]
@@ -23,29 +23,5 @@ values =
[bumpversion:file:passbook/__init__.py]
[bumpversion:file:passbook/api/__init__.py]
[bumpversion:file:passbook/core/__init__.py]
[bumpversion:file:passbook/admin/__init__.py]
[bumpversion:file:passbook/captcha_factor/__init__.py]
[bumpversion:file:passbook/oauth_client/__init__.py]
[bumpversion:file:passbook/ldap/__init__.py]
[bumpversion:file:passbook/lib/__init__.py]
[bumpversion:file:passbook/hibp_policy/__init__.py]
[bumpversion:file:passbook/password_expiry_policy/__init__.py]
[bumpversion:file:passbook/saml_idp/__init__.py]
[bumpversion:file:passbook/audit/__init__.py]
[bumpversion:file:passbook/oauth_provider/__init__.py]
[bumpversion:file:passbook/otp/__init__.py]
[bumpversion:file:docker/nginx.conf]

View File

@@ -1,12 +1,10 @@
[run]
source = passbook
omit =
env/
*/wsgi.py
manage.py
*/migrations/*
*/apps.py
passbook/management/commands/nexus_upload.py
passbook/management/commands/web.py
passbook/management/commands/worker.py
docs/

View File

@@ -2,3 +2,4 @@ env
helm
passbook-ui
static
*.env.yml

View File

@@ -9,3 +9,6 @@ insert_final_newline = true
[html]
indent_size = 2
[yaml]
indent_size = 2

1
.gitignore vendored
View File

@@ -191,3 +191,4 @@ pip-selfcheck.json
# End of https://www.gitignore.io/api/python,django
/static/
local.env.yml
.vscode/

View File

@@ -1,131 +1,135 @@
# Global Variables
before_script:
- "python3 -m pip install -U virtualenv"
- "virtualenv env"
- "source env/bin/activate"
- "pip3 install -U -r requirements-dev.txt"
stages:
- build-base-image
- build-dev-image
- test
- build
- docs
- deploy
image: python:3.6
services:
- postgres:latest
- package
image: docker.beryju.org/passbook/dev:latest
variables:
POSTGRES_DB: passbook
POSTGRES_USER: passbook
POSTGRES_PASSWORD: 'EK-5jnKfjrGRm<77'
POSTGRES_PASSWORD: "EK-5jnKfjrGRm<77"
before_script:
- pip install pipenv
# Ensure all dependencies are installed, even those not included in passbook/dev
# According to pipenv docs, -d outputs all packages, however it actually does not
- pipenv lock -r > requirements-all.txt
- pipenv lock -rd >> requirements-all.txt
- pip install -r requirements-all.txt
create-base-image:
image:
name: gcr.io/kaniko-project/executor:debug
entrypoint: [""]
before_script:
- echo "{\"auths\":{\"docker.beryju.org\":{\"auth\":\"$DOCKER_AUTH\"}}}" > /kaniko/.docker/config.json
script:
- /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/base.Dockerfile --destination docker.beryju.org/passbook/base:latest --destination docker.beryju.org/passbook/base:0.5.0-beta
stage: build-base-image
only:
refs:
- tags
- /^version/.*$/
build-dev-image:
image:
name: gcr.io/kaniko-project/executor:debug
entrypoint: [""]
before_script:
- echo "{\"auths\":{\"docker.beryju.org\":{\"auth\":\"$DOCKER_AUTH\"}}}" > /kaniko/.docker/config.json
script:
- /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/dev.Dockerfile --destination docker.beryju.org/passbook/dev:latest --destination docker.beryju.org/passbook/dev:0.5.0-beta
stage: build-dev-image
only:
refs:
- tags
- /^version/.*$/
include:
- /allauth/.gitlab-ci.yml
isort:
script:
- isort -c -sg env
stage: test
services:
- postgres:latest
- redis:latest
migrations:
script:
- python manage.py migrate
stage: test
prospector:
script:
- prospector
stage: test
pylint:
script:
- pylint passbook
stage: test
services:
- postgres:latest
- redis:latest
# prospector:
# script:
# - prospector
# stage: test
# services:
# - postgres:latest
# - redis:latest
# pylint:
# script:
# - pylint passbook
# stage: test
# services:
# - postgres:latest
# - redis:latest
coverage:
script:
- coverage run manage.py test
- coverage report
- coverage html
stage: test
bandit:
script:
- bandit -r passbook
stage: test
services:
- postgres:latest
- redis:latest
package-docker:
package-passbook-server:
image:
name: gcr.io/kaniko-project/executor:debug
entrypoint: [""]
before_script:
- echo "{\"auths\":{\"docker.$NEXUS_URL\":{\"auth\":\"$NEXUS_AUTH\"}}}" > /kaniko/.docker/config.json
- echo "{\"auths\":{\"docker.beryju.org\":{\"auth\":\"$DOCKER_AUTH\"}}}" > /kaniko/.docker/config.json
script:
- /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination docker.pkg.beryju.org/passbook:latest --destination docker.pkg.beryju.org/passbook:0.1.11-beta
- /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination docker.beryju.org/passbook/server:latest --destination docker.beryju.org/passbook/server:0.5.0-beta
stage: build
only:
- tags
- /^version/.*$/
package-helm:
build-passbook-static:
stage: build
script:
- curl https://raw.githubusercontent.com/helm/helm/master/scripts/get | bash
- helm init --client-only
- helm package helm/passbook
- ./manage.py nexus_upload --method put --url $NEXUS_URL --auth $NEXUS_AUTH --repo helm *.tgz
only:
- tags
- /^version/.*$/
package-debian:
image:
name: gcr.io/kaniko-project/executor:debug
entrypoint: [""]
before_script:
- apt update
- apt install -y --no-install-recommends build-essential debhelper devscripts equivs python3 python3-dev python3-pip libsasl2-dev libldap2-dev
- mk-build-deps debian/control
- apt install ./*build-deps*deb -f -y
- python3 -m pip install -U virtualenv pip
- virtualenv env
- source env/bin/activate
- pip3 install -U -r requirements.txt -r requirements-dev.txt
- ./manage.py collectstatic --no-input
image: ubuntu:18.04
- echo "{\"auths\":{\"docker.beryju.org\":{\"auth\":\"$DOCKER_AUTH\"}}}" > /kaniko/.docker/config.json
script:
- debuild -us -uc
- cp ../passbook*.deb .
- ./manage.py nexus_upload --method post --url $NEXUS_URL --auth $NEXUS_AUTH --repo apt passbook*deb
- /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/static.Dockerfile --destination docker.beryju.org/passbook/static:latest --destination docker.beryju.org/passbook/static:0.5.0-beta
only:
- tags
- /^version/.*$/
# running collectstatic fully initialises django, hence we need that databases
services:
- postgres:latest
- redis:latest
package-helm:
image: debian:stretch-slim
stage: package
before_script:
- apt update && apt install -y curl
- curl https://raw.githubusercontent.com/helm/helm/master/scripts/get | bash
script:
- helm init --client-only
- helm dependency update helm/passbook
- helm package helm/passbook
artifacts:
paths:
- passbook*deb
expire_in: 2 days
stage: build
- passbook-*.tgz
expire_in: 1 week
only:
- tags
- /^version/.*$/
# docs:
# stage: docs
# only:
# - master
# - tags
# - /^debian/.*$/
# environment:
# name: docs
# url: "https://passbook.beryju.org/docs/"
# script:
# - apt update
# - apt install -y rsync
# - "mkdir ~/.ssh"
# - "cp .gitlab/known_hosts ~/.ssh/"
# - "pip3 install -U -r requirements-docs.txt"
# - "eval $(ssh-agent -s)"
# - "echo \"${CI_SSH_PRIVATE}\" | ssh-add -"
# - mkdocs build
# - 'rsync -avh --delete web/* "beryjuorg@ory1-web-prod-1.ory1.beryju.org:passbook.beryju.org/"'
# - 'rsync -avh --delete site/* "beryjuorg@ory1-web-prod-1.ory1.beryju.org:passbook.beryju.org/docs/"'
deploy:
environment:
name: production
url: https://passbook-prod.default.k8s.beryju.org/
stage: deploy
only:
- tags
- /^version/.*$/
script:
- curl https://raw.githubusercontent.com/helm/helm/master/scripts/get | bash
- helm init --client-only
- helm repo add beryju.org https://pkg.beryju.org/repository/helm/
- helm repo update
- helm upgrade passbook-prod beryju.org/passbook --devel
- tags
- /^version/.*$/

View File

@@ -3,7 +3,6 @@ test-warnings: true
doc-warnings: false
ignore-paths:
- env
- migrations
- docs
- node_modules

View File

@@ -2,9 +2,10 @@
disable=redefined-outer-name,arguments-differ,no-self-use,cyclic-import,fixme,locally-disabled,unpacking-non-sequence,too-many-ancestors,too-many-branches,too-few-public-methods
load-plugins=pylint_django,pylint.extensions.bad_builtin
#,pylint.extensions.docparams
extension-pkg-whitelist=lxml
const-rgx=[a-zA-Z0-9_]{1,40}$
ignored-modules=django-otp
jobs=4
[SIMILARITIES]

View File

@@ -1,114 +0,0 @@
# The default ``config.py``
# flake8: noqa
def set_prefs(prefs):
"""This function is called before opening the project"""
# Specify which files and folders to ignore in the project.
# Changes to ignored resources are not added to the history and
# VCSs. Also they are not returned in `Project.get_files()`.
# Note that ``?`` and ``*`` match all characters but slashes.
# '*.pyc': matches 'test.pyc' and 'pkg/test.pyc'
# 'mod*.pyc': matches 'test/mod1.pyc' but not 'mod/1.pyc'
# '.svn': matches 'pkg/.svn' and all of its children
# 'build/*.o': matches 'build/lib.o' but not 'build/sub/lib.o'
# 'build//*.o': matches 'build/lib.o' and 'build/sub/lib.o'
prefs['ignored_resources'] = ['*.pyc', '*~', '.ropeproject',
'.hg', '.svn', '_svn', '.git', '.tox']
# Specifies which files should be considered python files. It is
# useful when you have scripts inside your project. Only files
# ending with ``.py`` are considered to be python files by
# default.
# prefs['python_files'] = ['*.py']
# Custom source folders: By default rope searches the project
# for finding source folders (folders that should be searched
# for finding modules). You can add paths to that list. Note
# that rope guesses project source folders correctly most of the
# time; use this if you have any problems.
# The folders should be relative to project root and use '/' for
# separating folders regardless of the platform rope is running on.
# 'src/my_source_folder' for instance.
# prefs.add('source_folders', 'src')
# You can extend python path for looking up modules
# prefs.add('python_path', '~/python/')
# Should rope save object information or not.
prefs['save_objectdb'] = True
prefs['compress_objectdb'] = False
# If `True`, rope analyzes each module when it is being saved.
prefs['automatic_soa'] = True
# The depth of calls to follow in static object analysis
prefs['soa_followed_calls'] = 0
# If `False` when running modules or unit tests "dynamic object
# analysis" is turned off. This makes them much faster.
prefs['perform_doa'] = True
# Rope can check the validity of its object DB when running.
prefs['validate_objectdb'] = True
# How many undos to hold?
prefs['max_history_items'] = 32
# Shows whether to save history across sessions.
prefs['save_history'] = True
prefs['compress_history'] = False
# Set the number spaces used for indenting. According to
# :PEP:`8`, it is best to use 4 spaces. Since most of rope's
# unit-tests use 4 spaces it is more reliable, too.
prefs['indent_size'] = 4
# Builtin and c-extension modules that are allowed to be imported
# and inspected by rope.
prefs['extension_modules'] = []
# Add all standard c-extensions to extension_modules list.
prefs['import_dynload_stdmods'] = True
# If `True` modules with syntax errors are considered to be empty.
# The default value is `False`; When `False` syntax errors raise
# `rope.base.exceptions.ModuleSyntaxError` exception.
prefs['ignore_syntax_errors'] = False
# If `True`, rope ignores unresolvable imports. Otherwise, they
# appear in the importing namespace.
prefs['ignore_bad_imports'] = False
# If `True`, rope will insert new module imports as
# `from <package> import <module>` by default.
prefs['prefer_module_from_imports'] = False
# If `True`, rope will transform a comma list of imports into
# multiple separate import statements when organizing
# imports.
prefs['split_imports'] = False
# If `True`, rope will remove all top-level import statements and
# reinsert them at the top of the module when making changes.
prefs['pull_imports_to_top'] = True
# If `True`, rope will sort imports alphabetically by module name instead
# of alphabetically by import statement, with from imports after normal
# imports.
prefs['sort_imports_alphabetically'] = False
# Location of implementation of
# rope.base.oi.type_hinting.interfaces.ITypeHintingFactory In general
# case, you don't have to change this value, unless you're an rope expert.
# Change this value to inject you own implementations of interfaces
# listed in module rope.base.oi.type_hinting.providers.interfaces
# For example, you can add you own providers for Django Models, or disable
# the search type-hinting in a class hierarchy, etc.
prefs['type_hinting_factory'] = (
'rope.base.oi.type_hinting.factory.default_type_hinting_factory')
def project_opened(project):
"""This function is called after opening the project"""
# Do whatever you like here!

Binary file not shown.

11
.vscode/settings.json vendored
View File

@@ -1,11 +0,0 @@
{
"python.pythonPath": "env/bin/python",
"editor.tabSize": 4,
"[html]": {
"editor.tabSize": 2
},
"cSpell.words": [
"SAML",
"passbook"
]
}

View File

@@ -1,34 +1,9 @@
FROM python:3.6-slim-stretch as build
FROM docker.beryju.org/passbook/base:test
COPY ./passbook/ /app/passbook
COPY ./manage.py /app/
COPY ./requirements.txt /app/
WORKDIR /app/
RUN apt-get update && apt-get install build-essential libssl-dev libffi-dev -y && \
mkdir /app/static/ && \
pip install -r requirements.txt && \
pip install psycopg2 && \
./manage.py collectstatic --no-input && \
apt-get remove --purge -y build-essential && \
apt-get autoremove --purge -y
FROM python:3.6-slim-stretch
COPY ./passbook/ /app/passbook
COPY ./manage.py /app/
COPY ./requirements.txt /app/
COPY --from=build /app/static /app/static/
WORKDIR /app/
RUN apt-get update && apt-get install build-essential libssl-dev libffi-dev -y && \
pip install -r requirements.txt && \
pip install psycopg2 && \
adduser --system --home /app/ passbook && \
chown -R passbook /app/ && \
apt-get remove --purge -y build-essential && \
apt-get autoremove --purge -y
COPY ./docker/uwsgi.ini /app/
USER passbook
WORKDIR /app/

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2018 BeryJu.org
Copyright (c) 2019 BeryJu.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

54
Pipfile Normal file
View File

@@ -0,0 +1,54 @@
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[packages]
celery = "*"
cherrypy = "*"
defusedxml = "*"
django = "*"
django-cors-middleware = "*"
django-filters = "*"
django-ipware = "*"
django-model-utils = "*"
django-oauth-toolkit = "*"
django-oidc-provider = "*"
django-otp = "*"
django-recaptcha = "*"
django-redis = "*"
django-rest-framework = "*"
djangorestframework = "==3.9.4"
drf-yasg = "*"
ldap3 = "*"
lxml = "*"
markdown = "*"
oauthlib = "*"
packaging = "*"
psycopg2-binary = "*"
pycryptodome = "*"
pyyaml = "*"
qrcode = "*"
requests-oauthlib = "*"
sentry-sdk = "*"
service_identity = "*"
signxml = "*"
urllib3 = {extras = ["secure"],version = "*"}
structlog = "*"
[requires]
python_version = "3.7"
[dev-packages]
astroid = "==2.2.5"
coverage = "*"
isort = "*"
pylint = "==2.3.1"
pylint-django = "==2.0.10"
prospector = "==1.1.7"
django-debug-toolbar = "*"
bumpversion = "*"
unittest-xml-reporting = "*"
autopep8 = "*"
bandit = "*"
colorama = "*"

1086
Pipfile.lock generated Normal file

File diff suppressed because it is too large Load Diff

9
README.md Normal file
View File

@@ -0,0 +1,9 @@
# passbook
## Quick instance
```
docker-compose pull
docker-compose up -d
docker-compose exec server ./manage.py createsuperuser
```

View File

@@ -1,27 +0,0 @@
# Global Variables
before_script:
- cd allauth/
- "python3 -m pip install -U virtualenv"
- "virtualenv env"
- "source env/bin/activate"
- "pip3 install -U -r requirements-dev.txt"
stages:
- test-allauth
image: python:3.6
isort:
script:
- isort -c -sg env
stage: test-allauth
prospector:
script:
- prospector
stage: test-allauth
pylint:
script:
- pylint passbook
stage: test-allauth
bandit:
script:
- bandit -r allauth_passbook
stage: test-allauth

View File

@@ -1,35 +0,0 @@
"""passbook provider"""
from allauth.socialaccount.providers.base import ProviderAccount
from allauth.socialaccount.providers.oauth2.provider import OAuth2Provider
class PassbookAccount(ProviderAccount):
"""passbook account"""
def to_str(self):
dflt = super().to_str()
return self.account.extra_data.get('username', dflt)
class PassbookProvider(OAuth2Provider):
"""passbook provider"""
id = 'passbook'
name = 'passbook'
account_class = PassbookAccount
def extract_uid(self, data):
return str(data['sub'])
def extract_common_fields(self, data):
return {
'email': data.get('email'),
'username': data.get('preferred_username'),
'name': data.get('name'),
}
def get_default_scope(self):
return ['openid:userinfo']
provider_classes = [PassbookProvider] # noqa

View File

@@ -1,5 +0,0 @@
"""passbook provider"""
from allauth.socialaccount.providers.oauth2.urls import default_urlpatterns
from allauth_passbook.provider import PassbookProvider
urlpatterns = default_urlpatterns(PassbookProvider)

View File

@@ -1,37 +0,0 @@
"""passbook adapter"""
import requests
from allauth.socialaccount import app_settings
from allauth.socialaccount.providers.oauth2.views import (OAuth2Adapter,
OAuth2CallbackView,
OAuth2LoginView)
from allauth_passbook.provider import PassbookProvider
class PassbookOAuth2Adapter(OAuth2Adapter):
"""passbook OAuth2 Adapter"""
provider_id = PassbookProvider.id
# pylint: disable=no-member
settings = app_settings.PROVIDERS.get(provider_id, {}) # noqa
provider_base_url = settings.get("PASSBOOK_URL", 'https://id.beryju.org')
access_token_url = '{0}/application/oauth/token/'.format(provider_base_url)
authorize_url = '{0}/application/oauth/authorize/'.format(provider_base_url)
profile_url = '{0}/api/v1/openid/'.format(
provider_base_url)
def complete_login(self, request, app, access_token, **kwargs):
headers = {
'Authorization': 'Bearer {0}'.format(access_token.token),
'Content-Type': 'application/json',
}
extra_data = requests.get(self.profile_url, headers=headers)
return self.get_provider().sociallogin_from_response(
request,
extra_data.json()
)
oauth2_login = OAuth2LoginView.adapter_view(PassbookOAuth2Adapter) # noqa
oauth2_callback = OAuth2CallbackView.adapter_view(PassbookOAuth2Adapter) # noqa

View File

@@ -1 +0,0 @@
django-allauth

View File

@@ -1,33 +0,0 @@
"""passbook allauth setup.py"""
from setuptools import setup
setup(
name='django-allauth-passbook',
version='1.0.0',
description='passbook support for django-allauth',
# long_description='\n'.join(read_simple('docs/index.md')[2:]),
long_description_content_type='text/markdown',
author='BeryJu.org',
author_email='hello@beryju.org',
packages=['allauth_passbook'],
include_package_data=True,
install_requires=['django-allauth'],
keywords='django allauth passbook',
license='MIT',
classifiers=[
'Intended Audience :: Developers',
'Topic :: Software Development :: Libraries :: Python Modules',
'Environment :: Web Environment',
'Topic :: Internet',
'License :: OSI Approved :: MIT License',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Framework :: Django',
'Framework :: Django :: 1.11',
'Framework :: Django :: 2.0',
'Framework :: Django :: 2.1',
],
)

19
base.Dockerfile Normal file
View File

@@ -0,0 +1,19 @@
FROM python:3.7-slim-stretch
COPY ./Pipfile /app/
COPY ./Pipfile.lock /app/
WORKDIR /app/
RUN apt-get update && \
apt-get install -y --no-install-recommends build-essential && \
pip install pipenv uwsgi --no-cache-dir && \
apt-get remove -y --purge build-essential && \
apt-get autoremove -y --purge && \
rm -rf /var/lib/apt/lists/*
RUN pipenv lock -r > requirements.txt && \
pipenv --rm && \
pip install -r requirements.txt --no-cache-dir && \
adduser --system --no-create-home passbook && \
chown -R passbook /app

52
debian/changelog vendored
View File

@@ -1,52 +0,0 @@
passbook (0.1.11) stable; urgency=medium
* add group administration
* bump version: 0.1.9-beta -> 0.1.10-beta
* fix helm labels being on deployments and not pods
* automatically deploy after release
* use Django's Admin FilteredSelectMultiple for Group Membership
* always use FilteredSelectMultiple for many-to-many fields
* Add Group Member policy
* add LDAP Group Membership Policy
-- Jens Langhammer <jens.langhammer@beryju.org> Sun, 10 Mar 2019 18:55:31 +0000
passbook (0.1.10) stable; urgency=high
* bump version: 0.1.7-beta -> 0.1.8-beta
* consistently using PolicyEngine
* add more Verbosity to PolicyEngine, rewrite SAML Authorisation check
* slightly refactor Factor View, add more unittests
* add impersonation middleware, add to templates
* bump version: 0.1.8-beta -> 0.1.9-beta
* fix k8s service routing http traffic to workers
* Fix button on policy test page
* better show loading state when testing a policy
-- Jens Langhammer <jens.langhammer@beryju.org> Sun, 10 Mar 2019 14:52:40 +0000
passbook (0.1.7) stable; urgency=medium
* bump version: 0.1.3-beta -> 0.1.4-beta
* implicitly add kubernetes-healthcheck-host in helm configmap
* fix debian build (again)
* add PropertyMapping Model, add Subclass for SAML, test with AWS
* add custom DynamicArrayField to better handle arrays
* format data before inserting it
* bump version: 0.1.4-beta -> 0.1.5-beta
* fix static files missing for debian package
* fix password not getting set on user import
* remove audit's login attempt
* add passing property to PolicyEngine
* fix captcha factor not loading keys from Factor class
* bump version: 0.1.5-beta -> 0.1.6-beta
* fix MATCH_EXACT not working as intended
* Improve access control for saml
-- Jens Langhammer <jens.langhammer@beryju.org> Fri, 08 Mar 2019 20:37:05 +0000
passbook (0.1.4) stable; urgency=medium
* initial debian package release
-- Jens Langhammer <jens.langhammer@beryju.org> Wed, 06 Mar 2019 18:22:41 +0000

1
debian/compat vendored
View File

@@ -1 +0,0 @@
10

20
debian/config vendored
View File

@@ -1,20 +0,0 @@
#!/bin/sh
# config maintainer script for passbook
set -e
# source debconf stuff
. /usr/share/debconf/confmodule
dbc_first_version=1.0.0
dbc_dbuser=passbook
dbc_dbname=passbook
# source dbconfig-common shell library, and call the hook function
if [ -f /usr/share/dbconfig-common/dpkg/config.pgsql ]; then
. /usr/share/dbconfig-common/dpkg/config.pgsql
dbc_go passbook "$@"
fi
#DEBHELPER#
exit 0

14
debian/control vendored
View File

@@ -1,14 +0,0 @@
Source: passbook
Section: admin
Priority: optional
Maintainer: BeryJu.org <support@beryju.org>
Uploaders: Jens Langhammer <jens@beryju.org>, BeryJu.org <support@beryju.org>
Build-Depends: debhelper (>= 10), dh-systemd (>= 1.5), dh-exec, wget, dh-exec, python3 (>= 3.5) | python3.6 | python3.7
Standards-Version: 3.9.6
Package: passbook
Architecture: all
Recommends: mysql-server, redis-server
Pre-Depends: adduser, libldap2-dev, libsasl2-dev
Depends: python3 (>= 3.5) | python3.6 | python3.7, python3-pip, dbconfig-pgsql | dbconfig-no-thanks, ${misc:Depends}
Description: Authentication Provider/Proxy supporting protocols like SAML, OAuth, LDAP and more.

22
debian/copyright vendored
View File

@@ -1,22 +0,0 @@
MIT License
Copyright (c) 2019 BeryJu.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

4
debian/dirs vendored
View File

@@ -1,4 +0,0 @@
etc/passbook/
etc/passbook/config.d/
var/log/passbook/
usr/share/passbook/

View File

@@ -1,44 +0,0 @@
debug: false
http:
host: 0.0.0.0
port: 8000
secret_key_file: /etc/passbook/secret_key
log:
level:
console: INFO
file: DEBUG
file: /var/log/passbook/passbook.log
# Error reporting, disabled by default
# error_report_enabled: true
# Set this to the server's external address.
# This is used to generate external URLs
external_url: http://image.example.com
# This dictates how the Path is generated
# can be either of:
# - view_sha512_short
# - view_md5
# - view_sha256
# - view_sha512
default_return_view: view_sha256
# Set this to true if you only want to use external authentication
external_auth_only: false
# If this is true, images are automatically claimed if the windows user exists
# in django
auto_claim_enabled: true
# LDAP Authentication
# ldap:
# enabled: false
# server:
# uri: 'ldap://dc1.example.com'
# tls: false
# bind:
# dn: ''
# password: ''
# search_base: ''
# filter: '(sAMAccountName=%(user)s)'
# require_group: ''

2
debian/gbp.conf vendored
View File

@@ -1,2 +0,0 @@
[buildpackage]
export-dir=../build-area

8
debian/install vendored
View File

@@ -1,8 +0,0 @@
passbook /usr/share/passbook/
static /usr/share/passbook/
manage.py /usr/share/passbook/
passbook.sh /usr/share/passbook/
vendor /usr/share/passbook/
debian/etc/passbook /etc/
debian/templates/database.yml /usr/share/passbook/

View File

@@ -1,14 +0,0 @@
[Unit]
Description=passbook - Authentication Provider/Proxy (Background worker)
After=network.target
Requires=network.target
[Service]
User=passbook
Group=passbook
WorkingDirectory=/usr/share/passbook
Type=simple
ExecStart=/usr/share/passbook/passbook.sh worker
[Install]
WantedBy=multi-user.target

View File

@@ -1,14 +0,0 @@
[Unit]
Description=passbook - Authentication Provider/Proxy
After=network.target
Requires=network.target
[Service]
User=passbook
Group=passbook
WorkingDirectory=/usr/share/passbook
Type=simple
ExecStart=/usr/share/passbook/passbook.sh web
[Install]
WantedBy=multi-user.target

36
debian/postinst vendored
View File

@@ -1,36 +0,0 @@
#!/bin/bash
set -e
. /usr/share/debconf/confmodule
. /usr/share/dbconfig-common/dpkg/postinst.pgsql
# you can set the default database encoding to something else
dbc_pgsql_createdb_encoding="UTF8"
dbc_generate_include=template:/etc/passbook/config.d/database.yml
dbc_generate_include_args="-o template_infile=/usr/share/passbook/database.yml"
dbc_go passbook "$@"
if [ -z "`getent group passbook`" ]; then
addgroup --quiet --system passbook
fi
if [ -z "`getent passwd passbook`" ]; then
echo " * Creating user and group passbook..."
adduser --quiet --system --home /usr/share/passbook --shell /bin/false --ingroup passbook --disabled-password --disabled-login --gecos "passbook User" passbook >> /var/log/passbook/passbook.log 2>&1
fi
echo " * Updating binary packages (psycopg2)"
python3 -m pip install --target=/usr/share/passbook/vendor/ --no-cache-dir --upgrade --force-reinstall psycopg2 >> /var/log/passbook/passbook.log 2>&1
if [ ! -f '/etc/passbook/secret_key' ]; then
echo " * Generating Secret Key"
python3 -c 'import random; result = "".join([random.choice("abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)") for i in range(50)]); print(result)' > /etc/passbook/secret_key 2> /dev/null
fi
chown -R passbook: /usr/share/passbook/
chown -R passbook: /etc/passbook/
chown -R passbook: /var/log/passbook/
chmod 440 /etc/passbook/secret_key
echo " * Running Database Migration"
/usr/share/passbook/passbook.sh migrate
echo " * A superuser can be created with this command '/usr/share/passbook/passbook.sh createsuperuser'"
echo " * You should probably also adjust your settings in '/etc/passbook/config.yml'"
#DEBHELPER#

24
debian/postrm vendored
View File

@@ -1,24 +0,0 @@
#!/bin/sh
set -e
if [ -f /usr/share/debconf/confmodule ]; then
. /usr/share/debconf/confmodule
fi
if [ -f /usr/share/dbconfig-common/dpkg/postrm.pgsql ]; then
. /usr/share/dbconfig-common/dpkg/postrm.pgsql
dbc_go passbook "$@"
fi
if [ "$1" = "purge" ]; then
if which ucf >/dev/null 2>&1; then
ucf --purge /etc/passbook/config.d/database.yml
ucfr --purge passbook /etc/passbook/config.d/database.yml
fi
rm -rf /etc/passbook/
rm -rf /usr/share/passbook/
fi
#DEBHELPER#

10
debian/prerm vendored
View File

@@ -1,10 +0,0 @@
#!/bin/sh
set -e
. /usr/share/debconf/confmodule
. /usr/share/dbconfig-common/dpkg/prerm.pgsql
dbc_go passbook "$@"
#DEBHELPER#

27
debian/rules vendored
View File

@@ -1,27 +0,0 @@
#!/usr/bin/make -f
# Uncomment this to turn on verbose mode.
# export DH_VERBOSE=1
%:
dh $@ --with=systemd
build-arch:
python3 -m pip install setuptools
python3 -m pip install --target=vendor/ -r requirements.txt
override_dh_strip:
dh_strip --exclude=psycopg2
override_dh_shlibdeps:
dh_shlibdeps --exclude=psycopg2
override_dh_installinit:
dh_installinit --name=passbook
dh_installinit --name=passbook-worker
dh_systemd_enable --name=passbook
dh_systemd_enable --name=passbook-worker
dh_systemd_start
# override_dh_usrlocal to do nothing
override_dh_usrlocal:

View File

@@ -1 +0,0 @@
3.0 (native)

View File

@@ -1,8 +0,0 @@
databases:
default:
engine: django.db.backends.postgresql
name: _DBC_DBNAME_
user: _DBC_DBUSER_
password: _DBC_DBPASS_
host: _DBC_DBSERVER_
port: _DBC_DBPORT_

5
dev.Dockerfile Normal file
View File

@@ -0,0 +1,5 @@
FROM docker.beryju.org/passbook/base:latest
RUN pipenv lock --dev -r > requirements-dev.txt && \
pipenv --rm && \
pip install -r /app/requirements-dev.txt --no-cache-dir

97
docker-compose.yml Normal file
View File

@@ -0,0 +1,97 @@
---
version: '3.2'
services:
postgresql:
image: postgres
volumes:
- database:/var/lib/postgresql/data
networks:
- internal
environment:
- POSTGRES_PASSWORD=${PG_PASS:-thisisnotagoodpassword}
- POSTGRES_USER=passbook
- POSTGRES_DB=passbook
labels:
- traefik.enable=false
redis:
image: redis
networks:
- internal
labels:
- traefik.enable=false
database-migrate:
build:
context: .
image: docker.beryju.org/passbook/server:${TAG:-test}
command:
- ./manage.py
- migrate
networks:
- internal
restart: 'no'
environment:
- PASSBOOK_REDIS__HOST=redis
- PASSBOOK_POSTGRESQL__HOST=postgresql
- PASSBOOK_POSTGRESQL__PASSWORD=${PG_PASS:-thisisnotagoodpassword}
server:
build:
context: .
image: docker.beryju.org/passbook/server:${TAG:-test}
command:
- uwsgi
- uwsgi.ini
environment:
- PASSBOOK_REDIS__HOST=redis
- PASSBOOK_POSTGRESQL__HOST=postgresql
- PASSBOOK_POSTGRESQL__PASSWORD=${PG_PASS:-thisisnotagoodpassword}
ports:
- 8000
networks:
- internal
labels:
- traefik.port=8000
- traefik.docker.network=internal
- traefik.frontend.rule=PathPrefix:/
worker:
image: docker.beryju.org/passbook/server:${TAG:-test}
command:
- ./manage.py
- worker
networks:
- internal
labels:
- traefik.enable=false
environment:
- PASSBOOK_REDIS__HOST=redis
- PASSBOOK_POSTGRESQL__HOST=postgresql
- PASSBOOK_POSTGRESQL__PASSWORD=${PG_PASS:-thisisnotagoodpassword}
static:
build:
context: .
dockerfile: static.Dockerfile
image: docker.beryju.org/passbook/static:${TAG:-test}
networks:
- internal
labels:
- traefik.frontend.rule=PathPrefix:/static, /robots.txt
- traefik.port=80
- traefik.docker.network=internal
traefik:
image: traefik:1.7
command: --api --docker
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
ports:
- "0.0.0.0:80:80"
- "0.0.0.0:443:443"
- "0.0.0.0:8080:8080"
networks:
- internal
volumes:
database:
driver: local
networks:
internal: {}

66
docker/nginx.conf Normal file
View File

@@ -0,0 +1,66 @@
user nginx;
worker_processes 1;
error_log stderr warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format json_combined escape=json
'{'
'"time_local":"$time_local",'
'"remote_addr":"$remote_addr",'
'"remote_user":"$remote_user",'
'"request":"$request",'
'"status": "$status",'
'"body_bytes_sent":"$body_bytes_sent",'
'"request_time":"$request_time",'
'"http_referrer":"$http_referer",'
'"http_user_agent":"$http_user_agent"'
'}';
access_log /dev/stdout json_combined;
sendfile on;
tcp_nopush on;
keepalive_timeout 65;
server {
server_name _;
gzip on;
gzip_types application/javascript image/* text/css;
gunzip on;
add_header X-passbook-Version 0.5.0-beta;
add_header Vary X-passbook-Version;
root /data/;
location /_/healthz {
return 204;
}
location ~* \.(jpg|jpeg|png|gif|ico)$ {
expires 30d;
}
location ~* \.(css|js)$ {
expires 7d;
}
}
server {
listen 8080;
location = /stub_status {
stub_status;
}
}
}

9
docker/uwsgi.ini Normal file
View File

@@ -0,0 +1,9 @@
[uwsgi]
http = 0.0.0.0:8000
chdir = /app
wsgi-file = passbook/root/wsgi.py
processes = 4
threads = 2
enable-threads = true
uid = passbook
gid = passbook

9
helm/passbook/Chart.lock Normal file
View File

@@ -0,0 +1,9 @@
dependencies:
- name: postgresql
repository: https://kubernetes-charts.storage.googleapis.com/
version: 6.3.10
- name: redis
repository: https://kubernetes-charts.storage.googleapis.com/
version: 9.2.1
digest: sha256:bdde250e1401dccdd5161e39c807f9e88b05e3e8e72e74df767a1bbb5fc39a4a
generated: "2019-10-01T10:46:06.542706+02:00"

View File

@@ -1,6 +1,6 @@
apiVersion: v1
appVersion: "0.1.11-beta"
appVersion: "0.5.0-beta"
description: A Helm chart for passbook.
name: passbook
version: "0.1.11-beta"
icon: https://passbook.beryju.org/images/logo.png
version: "0.5.0-beta"
icon: https://git.beryju.org/uploads/-/system/project/avatar/108/logo.png

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,9 +1,9 @@
dependencies:
- name: redis
repository: https://kubernetes-charts.storage.googleapis.com/
version: 5.1.0
- name: postgresql
repository: https://kubernetes-charts.storage.googleapis.com/
version: 3.10.1
digest: sha256:04bd136761f070e94a2ff32ff48ff87f5e07fbd451e5fd7f65551e3bd4680e5e
generated: 2019-02-08T12:08:49.090666+01:00
version: 4.2.2
- name: redis
repository: https://kubernetes-charts.storage.googleapis.com/
version: 9.2.1
digest: sha256:8782e974a1094eaeecf1d68f093ca4fb84977217b2bd38b09790a05ec289aec2
generated: "2019-10-02T21:03:25.90491153Z"

View File

@@ -1,7 +1,7 @@
dependencies:
- name: redis
version: 5.1.0
repository: https://kubernetes-charts.storage.googleapis.com/
- name: postgresql
version: 3.10.1
version: 4.2.2
repository: https://kubernetes-charts.storage.googleapis.com/
- name: redis
version: 9.2.1
repository: https://kubernetes-charts.storage.googleapis.com/

View File

@@ -4,40 +4,16 @@ metadata:
name: {{ include "passbook.fullname" . }}-config
data:
config.yml: |
# Env for Docker images
databases:
default:
engine: django.db.backends.postgresql
name: {{ .Values.postgresql.postgresqlDatabase }}
user: postgres
password: {{ .Values.postgresql.postgresqlPassword }}
host: {{ .Release.Name }}-postgresql
port: ''
log:
level:
console: DEBUG
file: DEBUG
file: /dev/null
syslog:
host: 127.0.0.1
port: 514
email:
host: localhost
port: 25
user: ''
password: ''
use_tls: false
use_ssl: false
from: passbook <passbook@domain.tld>
web:
listen: 0.0.0.0
port: 8000
threads: 30
debug: false
secure_proxy_header:
HTTP_X_FORWARDED_PROTO: https
redis: ":{{ .Values.redis.password }}@{{ .Release.Name }}-redis-master"
# Error reporting, sends stacktrace to sentry.services.beryju.org
postgresql:
host: "{{ .Release.Name }}-postgresql"
name: "{{ .Values.postgresql.postgresqlDatabase }}"
user: postgres
redis:
host: "{{ .Release.Name }}-redis-master"
cache_db: 0
message_queue_db: 1
# Error reporting, sends stacktrace to sentry.beryju.org
error_report_enabled: {{ .Values.config.error_reporting }}
{{- if .Values.config.secret_key }}
@@ -46,11 +22,12 @@ data:
secret_key: {{ randAlphaNum 50 }}
{{- end }}
primary_domain: {{ .Values.primary_domain }}
domains:
{{- range .Values.ingress.hosts }}
- {{ . | quote }}
{{- end }}
- kubernetes-healthcheck-host
{{- range .Values.ingress.hosts }}
- {{ . | quote }}
{{- end }}
- kubernetes-healthcheck-host
passbook:
sign_up:
@@ -123,6 +100,7 @@ data:
- passbook.oauth_client.source_types.reddit
- passbook.oauth_client.source_types.supervisr
- passbook.oauth_client.source_types.twitter
- passbook.oauth_client.source_types.azure_ad
saml_idp:
signing: true
autosubmit: false
@@ -131,9 +109,4 @@ data:
# List of python packages with provider types to load.
types:
- passbook.saml_idp.processors.generic
- passbook.saml_idp.processors.aws
- passbook.saml_idp.processors.gitlab
- passbook.saml_idp.processors.nextcloud
- passbook.saml_idp.processors.salesforce
- passbook.saml_idp.processors.shibboleth
- passbook.saml_idp.processors.wordpress_orange

View File

@@ -1,6 +1,5 @@
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "passbook.fullname" . -}}
{{- $ingressPath := .Values.ingress.path -}}
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
@@ -30,9 +29,17 @@ spec:
- host: {{ . | quote }}
http:
paths:
- path: {{ $ingressPath }}
- path: /
backend:
serviceName: {{ $fullName }}
serviceName: {{ $fullName }}-web
servicePort: http
- path: /static/
backend:
serviceName: {{ $fullName }}-static
servicePort: http
- path: /robots.txt
backend:
serviceName: {{ $fullName }}-static
servicePort: http
{{- end }}
{{- end }}

View File

@@ -1,67 +0,0 @@
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: {{ include "passbook.fullname" . }}-web
labels:
app.kubernetes.io/name: {{ include "passbook.name" . }}
helm.sh/chart: {{ include "passbook.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app.kubernetes.io/name: {{ include "passbook.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
template:
metadata:
labels:
app.kubernetes.io/name: {{ include "passbook.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
passbook.io/component: web
spec:
volumes:
- name: config-volume
configMap:
name: {{ include "passbook.fullname" . }}-config
containers:
- name: {{ .Chart.Name }}
image: "docker.pkg.beryju.org/passbook:{{ .Values.image.tag }}"
imagePullPolicy: IfNotPresent
command: ["/bin/sh","-c"]
args: ["./manage.py migrate && ./manage.py web"]
ports:
- name: http
containerPort: 8000
protocol: TCP
volumeMounts:
- mountPath: /etc/passbook
name: config-volume
livenessProbe:
httpGet:
path: /
port: http
httpHeaders:
- name: Host
value: kubernetes-healthcheck-host
readinessProbe:
httpGet:
path: /
port: http
httpHeaders:
- name: Host
value: kubernetes-healthcheck-host
resources:
{{ toYaml .Values.resources | indent 12 }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}

View File

@@ -0,0 +1,55 @@
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: {{ include "passbook.fullname" . }}-static
labels:
app.kubernetes.io/name: {{ include "passbook.name" . }}
helm.sh/chart: {{ include "passbook.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
spec:
selector:
matchLabels:
app.kubernetes.io/name: {{ include "passbook.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
template:
metadata:
labels:
app.kubernetes.io/name: {{ include "passbook.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
k8s.passbook.io/component: static
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: '9113'
field.cattle.io/workloadMetrics: '[{"path":"/metrics","port":9113,"schema":"HTTP"}]'
spec:
containers:
- name: {{ .Chart.Name }}-static
image: "docker.beryju.org/passbook/static:{{ .Values.image.tag }}"
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
protocol: TCP
livenessProbe:
initialDelaySeconds: 10
timeoutSeconds: 5
httpGet:
path: /_/healthz
port: http
readinessProbe:
initialDelaySeconds: 10
timeoutSeconds: 5
httpGet:
path: /_/healthz
port: http
resources:
requests:
cpu: 10m
memory: 10M
limits:
cpu: 20m
memory: 20M
- name: {{ .Chart.Name }}-static-prometheus
image: nginx/nginx-prometheus-exporter:0.4.1
imagePullPolicy: IfNotPresent

View File

@@ -0,0 +1,21 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "passbook.fullname" . }}-static
labels:
app.kubernetes.io/name: {{ include "passbook.name" . }}
helm.sh/chart: {{ include "passbook.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
k8s.passbook.io/component: static
spec:
type: ClusterIP
ports:
- port: 80
targetPort: http
protocol: TCP
name: http
selector:
app.kubernetes.io/name: {{ include "passbook.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
k8s.passbook.io/component: static

View File

@@ -0,0 +1,102 @@
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: {{ include "passbook.fullname" . }}-web
labels:
app.kubernetes.io/name: {{ include "passbook.name" . }}
helm.sh/chart: {{ include "passbook.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app.kubernetes.io/name: {{ include "passbook.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
template:
metadata:
labels:
app.kubernetes.io/name: {{ include "passbook.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
passbook.io/component: web
spec:
volumes:
- name: config-volume
configMap:
name: {{ include "passbook.fullname" . }}-config
initContainers:
- name: passbook-database-migrations
image: "docker.beryju.org/passbook/server:{{ .Values.image.tag }}"
command:
- ./manage.py
args:
- migrate
envFrom:
- configMapRef:
name: {{ include "passbook.fullname" . }}-config
prefix: PASSBOOK_
env:
- name: PASSBOOK_REDIS__PASSWORD
valueFrom:
secretKeyRef:
name: "{{ .Release.Name }}-redis"
key: redis-password
- name: PASSBOOK_POSTGRESQL__PASSWORD
valueFrom:
secretKeyRef:
name: "{{ .Release.Name }}-postgresql"
key: postgresql-password
volumeMounts:
- mountPath: /etc/passbook
name: config-volume
containers:
- name: {{ .Chart.Name }}
image: "docker.beryju.org/passbook/server:{{ .Values.image.tag }}"
imagePullPolicy: IfNotPresent
command:
- uwsgi
args:
- uwsgi.ini
envFrom:
- configMapRef:
name: {{ include "passbook.fullname" . }}-config
prefix: PASSBOOK_
env:
- name: PASSBOOK_REDIS__PASSWORD
valueFrom:
secretKeyRef:
name: "{{ .Release.Name }}-redis"
key: redis-password
- name: PASSBOOK_POSTGRESQL__PASSWORD
valueFrom:
secretKeyRef:
name: "{{ .Release.Name }}-postgresql"
key: postgresql-password
ports:
- name: http
containerPort: 8000
protocol: TCP
volumeMounts:
- mountPath: /etc/passbook
name: config-volume
livenessProbe:
httpGet:
path: /
port: http
httpHeaders:
- name: Host
value: kubernetes-healthcheck-host
readinessProbe:
httpGet:
path: /
port: http
httpHeaders:
- name: Host
value: kubernetes-healthcheck-host
resources:
requests:
cpu: 50m
memory: 150M
limits:
cpu: 200m
memory: 300M

View File

@@ -1,7 +1,7 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "passbook.fullname" . }}
name: {{ include "passbook.fullname" . }}-web
labels:
app.kubernetes.io/name: {{ include "passbook.name" . }}
helm.sh/chart: {{ include "passbook.chart" . }}

View File

@@ -26,9 +26,27 @@ spec:
name: {{ include "passbook.fullname" . }}-config
containers:
- name: {{ .Chart.Name }}
image: "docker.pkg.beryju.org/passbook:{{ .Values.image.tag }}"
image: "docker.beryju.org/passbook/server:{{ .Values.image.tag }}"
imagePullPolicy: IfNotPresent
command: ["./manage.py", "worker"]
command:
- ./manage.py
args:
- worker
envFrom:
- configMapRef:
name: {{ include "passbook.fullname" . }}-config
prefix: PASSBOOK_
env:
- name: PASSBOOK_REDIS__PASSWORD
valueFrom:
secretKeyRef:
name: "{{ .Release.Name }}-redis"
key: redis-password
- name: PASSBOOK_POSTGRESQL__PASSWORD
valueFrom:
secretKeyRef:
name: "{{ .Release.Name }}-postgresql"
key: postgresql-password
ports:
- name: http
containerPort: 8000
@@ -37,16 +55,9 @@ spec:
- mountPath: /etc/passbook
name: config-volume
resources:
{{ toYaml .Values.resources | indent 12 }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
requests:
cpu: 150m
memory: 300M
limits:
cpu: 300m
memory: 500M

View File

@@ -5,7 +5,7 @@
replicaCount: 1
image:
tag: 0.1.11-beta
tag: 0.5.0-beta
nameOverride: ""
@@ -14,10 +14,12 @@ config:
# secret_key: _k*@6h2u2@q-dku57hhgzb7tnx*ba9wodcb^s9g0j59@=y(@_o
# Enable error reporting
error_reporting: true
email:
host: localhost
postgresql:
postgresqlDatabase: passbook
postgresqlPassword: foo
postgresqlDatabase: passbook
postgresqlPassword: foo
service:
type: ClusterIP
@@ -31,27 +33,7 @@ ingress:
path: /
hosts:
- passbook.k8s.local
- kubernetes-healthcheck-host
defaultHost: passbook.k8s.local
tls: []
# - secretName: chart-example-tls
# hosts:
# - passbook.k8s.local
resources: {}
# We usually recommend not to specify default resources and to leave this as a conscious
# choice for the user. This also increases chances charts run on environments with little
# resources, such as Minikube. If you do want to specify resources, uncomment the following
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
nodeSelector: {}
tolerations: []
affinity: {}

View File

@@ -4,7 +4,7 @@ import os
import sys
if __name__ == '__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'passbook.core.settings')
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'passbook.root.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:

View File

@@ -1,7 +0,0 @@
#!/bin/bash
# Check if this file is a symlink, if so, read real base dir
BASE_DIR=$(dirname $(readlink -f ${BASH_SOURCE[0]}))
cd $BASE_DIR
PYTHONPATH="${BASE_DIR}/vendor/" python3 manage.py $@

View File

@@ -1,2 +1,2 @@
"""passbook"""
__version__ = '0.1.11-beta'
__version__ = '0.5.0-beta'

View File

@@ -1,2 +0,0 @@
"""passbook admin"""
__version__ = '0.1.11-beta'

View File

@@ -1,2 +0,0 @@
django-rest-framework
drf_yasg

View File

@@ -4,49 +4,4 @@
{% load is_active %}
{% block nav_secondary %}
<ul class="nav navbar-nav navbar-persistent">
<li class="{% is_active 'passbook_admin:overview' %}">
<a href="{% url 'passbook_admin:overview' %}">{% trans 'Overview' %}</a>
</li>
<li
class="{% is_active 'passbook_admin:applications' 'passbook_admin:application-create' 'passbook_admin:application-update' 'passbook_admin:application-delete' %}">
<a href="{% url 'passbook_admin:applications' %}">{% trans 'Applications' %}</a>
</li>
<li
class="{% is_active 'passbook_admin:sources' 'passbook_admin:source-create' 'passbook_admin:source-update' 'passbook_admin:source-delete' %}">
<a href="{% url 'passbook_admin:sources' %}">{% trans 'Sources' %}</a>
</li>
<li
class="{% is_active 'passbook_admin:providers' 'passbook_admin:provider-create' 'passbook_admin:provider-update' 'passbook_admin:provider-delete' %}">
<a href="{% url 'passbook_admin:providers' %}">{% trans 'Providers' %}</a>
</li>
<li
class="{% is_active 'passbook_admin:property-mappings' 'passbook_admin:property-mapping-create' 'passbook_admin:property-mapping-update' 'passbook_admin:property-mapping-delete' %}">
<a href="{% url 'passbook_admin:property-mappings' %}">{% trans 'Property Mappings' %}</a>
</li>
<li
class="{% is_active 'passbook_admin:factors' 'passbook_admin:factor-create' 'passbook_admin:factor-update' 'passbook_admin:factor-delete' %}">
<a href="{% url 'passbook_admin:factors' %}">{% trans 'Factors' %}</a>
</li>
<li
class="{% is_active 'passbook_admin:policies' 'passbook_admin:policy-create' 'passbook_admin:policy-update' 'passbook_admin:policy-delete' 'passbook_admin:policy-test' %}">
<a href="{% url 'passbook_admin:policies' %}">{% trans 'Policies' %}</a>
</li>
<li
class="{% is_active 'passbook_admin:invitations' 'passbook_admin:invitation-create' 'passbook_admin:invitation-update' 'passbook_admin:invitation-delete' 'passbook_admin:invitation-test' %}">
<a href="{% url 'passbook_admin:invitations' %}">{% trans 'Invitations' %}</a>
</li>
<li class="{% is_active 'passbook_admin:users' 'passbook_admin:user-update' 'passbook_admin:user-delete' %}">
<a href="{% url 'passbook_admin:users' %}">{% trans 'Users' %}</a>
</li>
<li class="{% is_active 'passbook_admin:groups' 'passbook_admin:group-update' 'passbook_admin:group-delete' %}">
<a href="{% url 'passbook_admin:groups' %}">{% trans 'Groups' %}</a>
</li>
<li class="{% is_active 'passbook_admin:audit-log' %}">
<a href="{% url 'passbook_admin:audit-log' %}">{% trans 'Audit Log' %}</a>
</li>
<li class="{% is_active_app 'admin' %}">
<a href="{% url 'admin:index' %}">{% trans 'Django' %}</a>
</li>
</ul>
{% endblock %}

View File

@@ -0,0 +1,31 @@
{% extends "administration/base.html" %}
{% load i18n %}
{% load utils %}
{% block title %}
{% title %}
{% endblock %}
{% block content %}
<div class="container">
<h1><span class="pficon-applications"></span> {% trans "Request" %}</h1>
<hr>
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>{% trans 'Key' %}</th>
<th>{% trans 'Value' %}</th>
</tr>
</thead>
<tbody>
{% for key, value in request_dict.items %}
<tr>
<td>{{ key }}</td>
<td>{{ value }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}

View File

@@ -152,10 +152,8 @@
<div class="col-xs-6 col-sm-2 col-md-2">
<div class="card-pf card-pf-accented card-pf-aggregate-status">
<h2 class="card-pf-title">
<a href="#">
<span class="pficon-bundle"></span>
<span class="card-pf-aggregate-status-count"></span> {% trans 'Version' %}
</a>
<span class="pficon-bundle"></span>
<span class="card-pf-aggregate-status-count"></span> {% trans 'Version' %}
</h2>
<div class="card-pf-body">
<p class="card-pf-aggregate-status-notifications">
@@ -181,8 +179,8 @@
<span class="card-pf-aggregate-status-notification">
<a href="#">
{% if worker_count < 1%}
<span class="pficon-error-circle-o" data-toggle="tooltip" data-placement="right"
title="{% trans 'No workers connected. Policies will not work and you may expect other issues.' %}"></span> {{ worker_count }}
<span class="pficon-warning-triangle-o" data-toggle="tooltip" data-placement="right"
title="{% trans 'No workers connected.' %}"></span> {{ worker_count }}
{% else %}
<span class="pficon pficon-ok"></span>{{ worker_count }}
{% endif %}
@@ -192,5 +190,59 @@
</div>
</div>
</div>
<div class="col-xs-6 col-sm-2 col-md-2">
<div class="card-pf card-pf-accented card-pf-aggregate-status">
<h2 class="card-pf-title">
<span class="pficon-server"></span>
<span class="card-pf-aggregate-status-count"></span> {% trans 'Cached Policies' %}
</h2>
<div class="card-pf-body">
<p class="card-pf-aggregate-status-notifications">
<span class="card-pf-aggregate-status-notification">
<a href="#" data-toggle="modal" data-target="#clearCacheMOdal">
{% if cached_policies < 1 %}
<span class="pficon-warning-triangle-o" data-toggle="tooltip" data-placement="right"
title="{% trans 'No policies cached. Users may experience slow response times.' %}"></span> {{ cached_policies }}
{% else %}
<span class="pficon pficon-ok"></span>{{ cached_policies }}
{% endif %}
</a>
</span>
</p>
</div>
</div>
</div>
</div>
<div class="modal fade" id="clearCacheMOdal" tabindex="-1" role="dialog" aria-labelledby="clearCacheMOdalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">
<span class="pficon pficon-close"></span>
</button>
<h4 class="modal-title" id="clearCacheMOdalLabel">{% trans 'Clear Cache' %}</h4>
</div>
<div class="modal-body">
<form method="post" id="clearForm">
{% csrf_token %}
<input type="hidden" name="clear">
<p>
{% blocktrans %}
Are you sure you want to clear the cache? This includes all user sessions and all cached Policy results.
{% endblocktrans %}
</p>
<h3>
{% blocktrans %}
This will also log you out.
{% endblocktrans %}
</h3>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button form="clearForm" type="submit" type="button" class="btn btn-danger">{% trans 'Clear' %}</button>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@@ -36,7 +36,7 @@
<tbody>
{% for property_mapping in object_list %}
<tr>
<td>{{ property_mapping.name }} ({{ property_mapping.slug }})</td>
<td>{{ property_mapping.name }}</td>
<td>{{ property_mapping|verbose_name }}</td>
<td>
<a class="btn btn-default btn-sm"

View File

@@ -57,6 +57,10 @@
<a class="btn btn-default btn-sm"
href="{{ href }}?back={{ request.get_full_path }}">{% trans name %}</a>
{% endfor %}
{% get_htmls provider as htmls %}
{% for html in htmls %}
{{ html|safe }}
{% endfor %}
</td>
</tr>
{% endfor %}

View File

@@ -36,7 +36,7 @@
<tr>
<td>{{ source.name }}</td>
<td>{{ source|fieldtype }}</td>
<td>{{ source.additional_info }}</td>
<td>{{ source.additional_info|safe }}</td>
<td>
<a class="btn btn-default btn-sm"
href="{% url 'passbook_admin:source-update' pk=source.uuid %}?back={{ request.get_full_path }}">{% trans 'Edit' %}</a>

View File

@@ -1,12 +1,14 @@
"""passbook admin templatetags"""
import inspect
from logging import getLogger
from django import template
from django.db.models import Model
from structlog import get_logger
from passbook.lib.utils.template import render_to_string
register = template.Library()
LOGGER = getLogger(__name__)
LOGGER = get_logger()
@register.simple_tag()
def get_links(model_instance):
@@ -29,3 +31,24 @@ def get_links(model_instance):
pass
return links
@register.simple_tag(takes_context=True)
def get_htmls(context, model_instance):
"""Find all html_ methods on an object instance, run them and return as dict"""
prefix = 'html_'
htmls = []
if not isinstance(model_instance, Model):
LOGGER.warning("Model %s is not instance of Model", model_instance)
return htmls
try:
for name, method in inspect.getmembers(model_instance, predicate=inspect.ismethod):
if name.startswith(prefix):
template, _context = method(context.get('request'))
htmls.append(render_to_string(template, _context))
except NotImplementedError:
pass
return htmls

View File

@@ -1,7 +1,7 @@
"""passbook URL Configuration"""
from django.urls import include, path
from passbook.admin.views import (applications, audit, factors, groups,
from passbook.admin.views import (applications, audit, debug, factors, groups,
invitations, overview, policy,
property_mapping, providers, sources, users)
@@ -77,5 +77,7 @@ urlpatterns = [
# Groups
path('groups/', groups.GroupListView.as_view(), name='groups'),
# API
path('api/', include('passbook.admin.api.urls'))
path('api/', include('passbook.admin.api.urls')),
# Debug
path('debug/request/', debug.DebugRequestView.as_view(), name='debug-request'),
]

View File

@@ -0,0 +1,17 @@
"""passbook administration debug views"""
from django.views.generic import TemplateView
from passbook.admin.mixins import AdminRequiredMixin
class DebugRequestView(AdminRequiredMixin, TemplateView):
"""Show debug info about request"""
template_name = 'administration/debug/request.html'
def get_context_data(self, **kwargs):
kwargs['request_dict'] = {}
for key in dir(self.request):
kwargs['request_dict'][key] = getattr(self.request, key)
return super().get_context_data(**kwargs)

View File

@@ -1,11 +1,13 @@
"""passbook administration overview"""
from django.core.cache import cache
from django.shortcuts import redirect, reverse
from django.views.generic import TemplateView
from passbook.admin.mixins import AdminRequiredMixin
from passbook.core import __version__
from passbook.core.celery import CELERY_APP
from passbook.core.models import (Application, Factor, Invitation, Policy,
Provider, Source, User)
from passbook.root.celery import CELERY_APP
class AdministrationOverviewView(AdminRequiredMixin, TemplateView):
@@ -13,6 +15,13 @@ class AdministrationOverviewView(AdminRequiredMixin, TemplateView):
template_name = 'administration/overview.html'
def post(self, *args, **kwargs):
"""Handle post (clear cache from modal)"""
if 'clear' in self.request.POST:
cache.clear()
return redirect(reverse('passbook_core:auth-login'))
return self.get(*args, **kwargs)
def get_context_data(self, **kwargs):
kwargs['application_count'] = len(Application.objects.all())
kwargs['policy_count'] = len(Policy.objects.all())
@@ -25,4 +34,5 @@ class AdministrationOverviewView(AdminRequiredMixin, TemplateView):
kwargs['worker_count'] = len(CELERY_APP.control.ping(timeout=0.5))
kwargs['providers_without_application'] = Provider.objects.filter(application=None)
kwargs['policies_without_attachment'] = len(Policy.objects.filter(policymodel__isnull=True))
kwargs['cached_policies'] = len(cache.keys('policy_*'))
return super().get_context_data(**kwargs)

View File

@@ -11,8 +11,8 @@ from django.views.generic.detail import DetailView
from passbook.admin.forms.policies import PolicyTestForm
from passbook.admin.mixins import AdminRequiredMixin
from passbook.core.models import Policy
from passbook.core.policies import PolicyEngine
from passbook.lib.utils.reflection import path_to_class
from passbook.policy.engine import PolicyEngine
class PolicyListView(AdminRequiredMixin, ListView):

View File

@@ -1,2 +0,0 @@
"""passbook api"""
__version__ = '0.1.11-beta'

View File

@@ -1,3 +0,0 @@
django-rest-framework
drf_yasg
django-filters

BIN
passbook/app_gw/.DS_Store vendored Normal file

Binary file not shown.

5
passbook/app_gw/admin.py Normal file
View File

@@ -0,0 +1,5 @@
"""passbook Application Security Gateway model admin"""
from passbook.lib.admin import admin_autoregister
admin_autoregister('passbook_app_gw')

11
passbook/app_gw/apps.py Normal file
View File

@@ -0,0 +1,11 @@
"""passbook Application Security Gateway app"""
from django.apps import AppConfig
class PassbookApplicationApplicationGatewayConfig(AppConfig):
"""passbook app_gw app"""
name = 'passbook.app_gw'
label = 'passbook_app_gw'
verbose_name = 'passbook Application Security Gateway'
# mountpoint = 'app_gw/'

66
passbook/app_gw/forms.py Normal file
View File

@@ -0,0 +1,66 @@
"""passbook Application Security Gateway Forms"""
from urllib.parse import urlparse
from django import forms
from django.contrib.admin.widgets import FilteredSelectMultiple
from django.forms import ValidationError
from django.utils.translation import gettext as _
from passbook.app_gw.models import ApplicationGatewayProvider, RewriteRule
from passbook.lib.fields import DynamicArrayField
class ApplicationGatewayProviderForm(forms.ModelForm):
"""Security Gateway Provider form"""
def clean_server_name(self):
"""Check if server_name is in DB already, since
Postgres ArrayField doesn't suppport keys."""
current = self.cleaned_data.get('server_name')
if ApplicationGatewayProvider.objects \
.filter(server_name__overlap=current) \
.exclude(pk=self.instance.pk).exists():
raise ValidationError(_("Server Name already in use."))
return current
def clean_upstream(self):
"""Check that upstream begins with http(s)"""
for upstream in self.cleaned_data.get('upstream'):
_parsed_url = urlparse(upstream)
if _parsed_url.scheme not in ('http', 'https'):
raise ValidationError(_("URL Scheme must be either http or https"))
return self.cleaned_data.get('upstream')
class Meta:
model = ApplicationGatewayProvider
fields = ['server_name', 'upstream', 'enabled', 'authentication_header',
'default_content_type', 'upstream_ssl_verification', 'property_mappings']
widgets = {
'authentication_header': forms.TextInput(),
'default_content_type': forms.TextInput(),
'property_mappings': FilteredSelectMultiple(_('Property Mappings'), False)
}
field_classes = {
'server_name': DynamicArrayField,
'upstream': DynamicArrayField
}
labels = {
'upstream_ssl_verification': _('Verify upstream SSL Certificates?'),
'property_mappings': _('Rewrite Rules')
}
class RewriteRuleForm(forms.ModelForm):
"""Rewrite Rule Form"""
class Meta:
model = RewriteRule
fields = ['name', 'match', 'halt', 'replacement', 'redirect', 'conditions']
widgets = {
'name': forms.TextInput(),
'match': forms.TextInput(attrs={'data-is-monospace': True}),
'replacement': forms.TextInput(attrs={'data-is-monospace': True}),
'conditions': FilteredSelectMultiple(_('Conditions'), False)
}

BIN
passbook/app_gw/migrations/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,50 @@
# Generated by Django 2.1.7 on 2019-03-20 21:38
import django.contrib.postgres.fields
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
('passbook_core', '0020_groupmembershippolicy'),
]
operations = [
migrations.CreateModel(
name='ApplicationGatewayProvider',
fields=[
('provider_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='passbook_core.Provider')),
('server_name', django.contrib.postgres.fields.ArrayField(base_field=models.TextField(), size=None)),
('upstream', django.contrib.postgres.fields.ArrayField(base_field=models.TextField(), size=None)),
('enabled', models.BooleanField(default=True)),
('authentication_header', models.TextField(default='X-Remote-User')),
('default_content_type', models.TextField(default='application/octet-stream')),
('upstream_ssl_verification', models.BooleanField(default=True)),
],
options={
'verbose_name': 'Application Gateway Provider',
'verbose_name_plural': 'Application Gateway Providers',
},
bases=('passbook_core.provider',),
),
migrations.CreateModel(
name='RewriteRule',
fields=[
('propertymapping_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='passbook_core.PropertyMapping')),
('match', models.TextField()),
('halt', models.BooleanField(default=False)),
('replacement', models.TextField()),
('redirect', models.CharField(choices=[('internal', 'Internal'), (301, 'Moved Permanently'), (302, 'Found')], max_length=50)),
('conditions', models.ManyToManyField(to='passbook_core.Policy')),
],
options={
'verbose_name': 'Rewrite Rule',
'verbose_name_plural': 'Rewrite Rules',
},
bases=('passbook_core.propertymapping',),
),
]

View File

@@ -0,0 +1,18 @@
# Generated by Django 2.1.7 on 2019-03-21 15:21
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('passbook_app_gw', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='rewriterule',
name='conditions',
field=models.ManyToManyField(blank=True, to='passbook_core.Policy'),
),
]

View File

@@ -0,0 +1,18 @@
# Generated by Django 2.2 on 2019-04-11 13:14
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('passbook_app_gw', '0002_auto_20190321_1521'),
]
operations = [
migrations.AlterField(
model_name='applicationgatewayprovider',
name='authentication_header',
field=models.TextField(blank=True, default='X-Remote-User'),
),
]

74
passbook/app_gw/models.py Normal file
View File

@@ -0,0 +1,74 @@
"""passbook app_gw models"""
import re
from django.contrib.postgres.fields import ArrayField
from django.db import models
from django.utils.translation import gettext as _
from passbook.core.models import Policy, PropertyMapping, Provider
class ApplicationGatewayProvider(Provider):
"""Virtual server which proxies requests to any hostname in server_name to upstream"""
server_name = ArrayField(models.TextField())
upstream = ArrayField(models.TextField())
enabled = models.BooleanField(default=True)
authentication_header = models.TextField(default='X-Remote-User', blank=True)
default_content_type = models.TextField(default='application/octet-stream')
upstream_ssl_verification = models.BooleanField(default=True)
form = 'passbook.app_gw.forms.ApplicationGatewayProviderForm'
@property
def name(self):
"""since this model has no name property, return a joined list of server_names as name"""
return ', '.join(self.server_name)
def __str__(self):
return "Application Gateway %s" % ', '.join(self.server_name)
class Meta:
verbose_name = _('Application Gateway Provider')
verbose_name_plural = _('Application Gateway Providers')
class RewriteRule(PropertyMapping):
"""Rewrite requests matching `match` with `replacement`, if all polcies in `conditions` apply"""
REDIRECT_INTERNAL = 'internal'
REDIRECT_PERMANENT = 301
REDIRECT_FOUND = 302
REDIRECTS = (
(REDIRECT_INTERNAL, _('Internal')),
(REDIRECT_PERMANENT, _('Moved Permanently')),
(REDIRECT_FOUND, _('Found')),
)
match = models.TextField()
halt = models.BooleanField(default=False)
conditions = models.ManyToManyField(Policy, blank=True)
replacement = models.TextField() # python formatted strings, use {match.1}
redirect = models.CharField(max_length=50, choices=REDIRECTS)
form = 'passbook.app_gw.forms.RewriteRuleForm'
_matcher = None
@property
def compiled_matcher(self):
"""Cache the compiled regex in memory"""
if not self._matcher:
self._matcher = re.compile(self.match)
return self._matcher
def __str__(self):
return "Rewrite Rule %s" % self.name
class Meta:
verbose_name = _('Rewrite Rule')
verbose_name_plural = _('Rewrite Rules')

View File

@@ -1,2 +0,0 @@
"""passbook audit Header"""
__version__ = '0.1.11-beta'

View File

@@ -1,6 +1,4 @@
"""passbook audit models"""
from logging import getLogger
from django.conf import settings
from django.contrib.auth.models import AnonymousUser
from django.contrib.postgres.fields import JSONField
@@ -8,10 +6,11 @@ from django.core.exceptions import ValidationError
from django.db import models
from django.utils.translation import gettext as _
from ipware import get_client_ip
from structlog import get_logger
from passbook.lib.models import UUIDModel
LOGGER = getLogger(__name__)
LOGGER = get_logger()
class AuditEntry(UUIDModel):
"""An individual audit log entry"""
@@ -22,7 +21,7 @@ class AuditEntry(UUIDModel):
ACTION_AUTHORIZE_APPLICATION = 'authorize_application'
ACTION_SUSPICIOUS_REQUEST = 'suspicious_request'
ACTION_SIGN_UP = 'sign_up'
ACTION_PASSWORD_RESET = 'password_reset' # noqa
ACTION_PASSWORD_RESET = 'password_reset' # noqa # nosec
ACTION_INVITE_CREATED = 'invitation_created'
ACTION_INVITE_USED = 'invitation_used'
ACTIONS = (

View File

@@ -1,2 +0,0 @@
"""passbook captcha_factor Header"""
__version__ = '0.1.11-beta'

View File

@@ -1 +0,0 @@
django-recaptcha

View File

@@ -1,2 +1,2 @@
"""passbook core"""
__version__ = '0.1.11-beta'
__version__ = '0.2.6-beta'

View File

@@ -1,12 +1,12 @@
"""passbook core app config"""
from importlib import import_module
from logging import getLogger
from django.apps import AppConfig
from structlog import get_logger
from passbook.lib.config import CONFIG
LOGGER = getLogger(__name__)
LOGGER = get_logger()
class PassbookCoreConfig(AppConfig):
"""passbook core app config"""
@@ -14,13 +14,14 @@ class PassbookCoreConfig(AppConfig):
name = 'passbook.core'
label = 'passbook_core'
verbose_name = 'passbook Core'
mountpoint = ''
def ready(self):
import_module('passbook.core.policies')
import_module('passbook.policy.engine')
factors_to_load = CONFIG.y('passbook.factors', [])
for factors_to_load in factors_to_load:
try:
import_module(factors_to_load)
LOGGER.info("Loaded %s", factors_to_load)
LOGGER.info("Loaded factor", factor_class=factors_to_load)
except ImportError as exc:
LOGGER.debug(exc)

View File

@@ -19,7 +19,7 @@ class AuthenticationFactor(TemplateView):
self.authenticator = authenticator
def get_context_data(self, **kwargs):
kwargs['config'] = CONFIG.get('passbook')
kwargs['config'] = CONFIG.y('passbook')
kwargs['is_login'] = True
kwargs['title'] = _('Log in to your account')
kwargs['primary_action'] = _('Log in')

View File

@@ -1,9 +1,9 @@
"""passbook multi-factor authentication engine"""
from logging import getLogger
from structlog import get_logger
from passbook.core.auth.factor import AuthenticationFactor
LOGGER = getLogger(__name__)
LOGGER = get_logger()
class DummyFactor(AuthenticationFactor):

View File

@@ -1,13 +1,15 @@
"""passbook multi-factor authentication engine"""
from logging import getLogger
from inspect import Signature
from django.contrib import messages
from django.contrib.auth import authenticate
from django.contrib.auth import _clean_credentials
from django.contrib.auth.signals import user_login_failed
from django.core.exceptions import PermissionDenied
from django.forms.utils import ErrorList
from django.shortcuts import redirect, reverse
from django.utils.translation import gettext as _
from django.views.generic import FormView
from structlog import get_logger
from passbook.core.auth.factor import AuthenticationFactor
from passbook.core.auth.view import AuthenticationView
@@ -15,10 +17,40 @@ from passbook.core.forms.authentication import PasswordFactorForm
from passbook.core.models import Nonce
from passbook.core.tasks import send_email
from passbook.lib.config import CONFIG
from passbook.lib.utils.reflection import path_to_class
LOGGER = getLogger(__name__)
LOGGER = get_logger()
def authenticate(request, backends, **credentials):
"""If the given credentials are valid, return a User object.
Customized version of django's authenticate, which accepts a list of backends"""
for backend_path in backends:
backend = path_to_class(backend_path)()
try:
signature = Signature.from_callable(backend.authenticate)
signature.bind(request, **credentials)
except TypeError:
LOGGER.debug("Backend doesn't accept our arguments", backend=backend)
# This backend doesn't accept these credentials as arguments. Try the next one.
continue
LOGGER.debug('Attempting authentication...', backend=backend)
try:
user = backend.authenticate(request, **credentials)
except PermissionDenied:
LOGGER.debug('Backend threw PermissionDenied', backend=backend)
# This backend says to stop in our tracks - this user should not be allowed in at all.
break
if user is None:
continue
# Annotate the user object with the path of the backend.
user.backend = backend_path
return user
# The credentials supplied are invalid to all backends, fire signal
user_login_failed.send(sender=__name__, credentials=_clean_credentials(
credentials), request=request)
class PasswordFactor(FormView, AuthenticationFactor):
"""Authentication factor which authenticates against django's AuthBackend"""
@@ -57,7 +89,7 @@ class PasswordFactor(FormView, AuthenticationFactor):
for uid_field in uid_fields:
kwargs[uid_field] = getattr(self.authenticator.pending_user, uid_field)
try:
user = authenticate(self.request, **kwargs)
user = authenticate(self.request, self.authenticator.current_factor.backends, **kwargs)
if user:
# User instance returned from authenticate() has .backend property set
self.authenticator.pending_user = user
@@ -72,5 +104,5 @@ class PasswordFactor(FormView, AuthenticationFactor):
return self.form_invalid(form)
except PermissionDenied:
# User was found, but permission was denied (i.e. user is not active)
LOGGER.debug("Denied access to %s", kwargs)
LOGGER.debug("Denied access", **kwargs)
return self.authenticator.user_invalid()

View File

@@ -1,19 +1,20 @@
"""passbook multi-factor authentication engine"""
from logging import getLogger
from typing import List, Tuple
from django.contrib.auth import login
from django.contrib.auth.mixins import UserPassesTestMixin
from django.shortcuts import get_object_or_404, redirect, reverse
from django.utils.http import urlencode
from django.views.generic import View
from structlog import get_logger
from passbook.core.models import Factor, User
from passbook.core.policies import PolicyEngine
from passbook.core.views.utils import PermissionDeniedView
from passbook.lib.utils.reflection import class_to_path, path_to_class
from passbook.lib.utils.urls import is_url_absolute
from passbook.policy.engine import PolicyEngine
LOGGER = getLogger(__name__)
LOGGER = get_logger()
def _redirect_with_qs(view, get_query_set=None):
"""Wrapper to redirect whilst keeping GET Parameters"""
@@ -29,13 +30,14 @@ class AuthenticationView(UserPassesTestMixin, View):
SESSION_PENDING_FACTORS = 'passbook_pending_factors'
SESSION_PENDING_USER = 'passbook_pending_user'
SESSION_USER_BACKEND = 'passbook_user_backend'
SESSION_IS_SSO_LOGIN = 'passbook_sso_login'
pending_user = None
pending_factors = []
pending_user: User
pending_factors: List[Tuple[str, str]] = []
_current_factor_class = None
_current_factor_class: Factor
current_factor = None
current_factor: Factor
# Allow only not authenticated users to login
def test_func(self):
@@ -59,10 +61,13 @@ class AuthenticationView(UserPassesTestMixin, View):
_all_factors = Factor.objects.filter(enabled=True).order_by('order').select_subclasses()
pending_factors = []
for factor in _all_factors:
LOGGER.debug("Checking if factor applies to user",
factor=factor, user=self.pending_user)
policy_engine = PolicyEngine(factor.policies.all())
policy_engine.for_user(self.pending_user).with_request(self.request).build()
if policy_engine.passing:
pending_factors.append((factor.uuid.hex, factor.type))
LOGGER.debug("Factor applies", factor=factor, user=self.pending_user)
return pending_factors
def dispatch(self, request, *args, **kwargs):
@@ -79,6 +84,10 @@ class AuthenticationView(UserPassesTestMixin, View):
if AuthenticationView.SESSION_FACTOR not in request.session:
# Case when no factors apply to user, return error denied
if not self.pending_factors:
# Case when user logged in from SSO provider and no more factors apply
if AuthenticationView.SESSION_IS_SSO_LOGIN in request.session:
LOGGER.debug("User authenticated with SSO, logging in...")
return self._user_passed()
return self.user_invalid()
factor_uuid, factor_class = self.pending_factors[0]
else:
@@ -94,17 +103,18 @@ class AuthenticationView(UserPassesTestMixin, View):
def get(self, request, *args, **kwargs):
"""pass get request to current factor"""
LOGGER.debug("Passing GET to %s", class_to_path(self._current_factor_class.__class__))
LOGGER.debug("Passing GET", view_class=class_to_path(self._current_factor_class.__class__))
return self._current_factor_class.get(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
"""pass post request to current factor"""
LOGGER.debug("Passing POST to %s", class_to_path(self._current_factor_class.__class__))
LOGGER.debug("Passing POST", view_class=class_to_path(self._current_factor_class.__class__))
return self._current_factor_class.post(request, *args, **kwargs)
def user_ok(self):
"""Redirect to next Factor"""
LOGGER.debug("Factor %s passed", class_to_path(self._current_factor_class.__class__))
LOGGER.debug("Factor passed",
factor_class=class_to_path(self._current_factor_class.__class__))
# Remove passed factor from pending factors
current_factor_tuple = (self.current_factor.uuid.hex,
class_to_path(self._current_factor_class.__class__))
@@ -117,7 +127,7 @@ class AuthenticationView(UserPassesTestMixin, View):
self.request.session[AuthenticationView.SESSION_PENDING_FACTORS] = \
self.pending_factors
self.request.session[AuthenticationView.SESSION_FACTOR] = next_factor
LOGGER.debug("Rendering Factor is %s", next_factor)
LOGGER.debug("Rendering Factor", next_factor=next_factor)
return _redirect_with_qs('passbook_core:auth-process', self.request.GET)
# User passed all factors
LOGGER.debug("User passed all factors, logging in")
@@ -134,7 +144,7 @@ class AuthenticationView(UserPassesTestMixin, View):
"""User Successfully passed all factors"""
backend = self.request.session[AuthenticationView.SESSION_USER_BACKEND]
login(self.request, self.pending_user, backend=backend)
LOGGER.debug("Logged in user %s", self.pending_user)
LOGGER.debug("Logged in", user=self.pending_user)
# Cleanup
self.cleanup()
next_param = self.request.GET.get('next', None)

Some files were not shown because too many files have changed in this diff Show More