Compare commits

..

11 Commits

33 changed files with 150 additions and 80 deletions

View File

@ -1,5 +1,5 @@
[bumpversion] [bumpversion]
current_version = 0.1.12-beta current_version = 0.1.16-beta
tag = True tag = True
commit = True commit = True
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\-(?P<release>.*) parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\-(?P<release>.*)

View File

@ -54,7 +54,7 @@ package-docker:
before_script: before_script:
- echo "{\"auths\":{\"docker.$NEXUS_URL\":{\"auth\":\"$NEXUS_AUTH\"}}}" > /kaniko/.docker/config.json - echo "{\"auths\":{\"docker.$NEXUS_URL\":{\"auth\":\"$NEXUS_AUTH\"}}}" > /kaniko/.docker/config.json
script: 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.12-beta - /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.16-beta
stage: build stage: build
only: only:
- tags - tags

18
debian/changelog vendored
View File

@ -1,3 +1,21 @@
passbook (0.1.16) stable; urgency=medium
* Replace redis with RabbitMQ
* updated debian package to suggest RabbitMQ
* update helm chart to require RabbitMQ
* fix invalid default config in debian package
-- Jens Langhammer <jens.langhammer@beryju.org> Mon, 11 Mar 2019 10:28:36 +0000
passbook (0.1.14) stable; urgency=medium
* bump version: 0.1.11-beta -> 0.1.12-beta
* Fix DoesNotExist error when running PolicyEngine against None user
* allow custom email server for helm installs
* fix UserChangePasswordView not requiring Login
-- Jens Langhammer <jens.langhammer@beryju.org> Mon, 11 Mar 2019 10:28:36 +0000
passbook (0.1.12) stable; urgency=medium passbook (0.1.12) stable; urgency=medium
* bump version: 0.1.10-beta -> 0.1.11-beta * bump version: 0.1.10-beta -> 0.1.11-beta

2
debian/control vendored
View File

@ -8,7 +8,7 @@ Standards-Version: 3.9.6
Package: passbook Package: passbook
Architecture: all Architecture: all
Recommends: mysql-server, redis-server Recommends: mysql-server, rabbitmq-server
Pre-Depends: adduser, libldap2-dev, libsasl2-dev Pre-Depends: adduser, libldap2-dev, libsasl2-dev
Depends: python3 (>= 3.5) | python3.6 | python3.7, python3-pip, dbconfig-pgsql | dbconfig-no-thanks, ${misc:Depends} 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. Description: Authentication Provider/Proxy supporting protocols like SAML, OAuth, LDAP and more.

View File

@ -1,4 +1,3 @@
debug: false
http: http:
host: 0.0.0.0 host: 0.0.0.0
port: 8000 port: 8000
@ -8,37 +7,71 @@ log:
console: INFO console: INFO
file: DEBUG file: DEBUG
file: /var/log/passbook/passbook.log file: /var/log/passbook/passbook.log
# Error reporting, disabled by default debug: false
# error_report_enabled: true secure_proxy_header:
HTTP_X_FORWARDED_PROTO: https
rabbitmq: guest:guest@localhost/passbook
# Error reporting, sends stacktrace to sentry.services.beryju.org
error_report_enabled: true
# Set this to the server's external address. passbook:
# This is used to generate external URLs sign_up:
external_url: http://image.example.com # Enables signup, created users are stored in internal Database and created in LDAP if ldap.create_users is true
enabled: true
# This dictates how the Path is generated password_reset:
# can be either of: # Enable password reset, passwords are reset in internal Database and in LDAP if ldap.reset_password is true
# - view_sha512_short enabled: true
# - view_md5 # Verification the user has to provide in order to be able to reset passwords. Can be any combination of `email`, `2fa`, `security_questions`
# - view_sha256 verification:
# - view_sha512 - email
default_return_view: view_sha256 # Text used in title, on login page and multiple other places
branding: passbook
# Set this to true if you only want to use external authentication login:
external_auth_only: false # Override URL used for logo
logo_url: null
# If this is true, images are automatically claimed if the windows user exists # Override URL used for Background on Login page
# in django bg_url: null
auto_claim_enabled: true # Optionally add a subtext, placed below logo on the login page
subtext: null
# LDAP Authentication footer:
# ldap: links:
# enabled: false # Optionally add links to the footer on the login page
# server: # - name: test
# uri: 'ldap://dc1.example.com' # href: https://test
# tls: false # Specify which fields can be used to authenticate. Can be any combination of `username` and `email`
# bind: uid_fields:
# dn: '' - username
# password: '' - email
# search_base: '' session:
# filter: '(sAMAccountName=%(user)s)' remember_age: 2592000 # 60 * 60 * 24 * 30, one month
# require_group: '' # Provider-specific settings
ldap:
# Which field from `uid_fields` maps to which LDAP Attribute
login_field_map:
username: sAMAccountName
email: mail # or userPrincipalName
user_attribute_map:
active_directory:
username: "%(sAMAccountName)s"
email: "%(mail)s"
name: "%(displayName)"
oauth_client:
# List of python packages with sources types to load.
types:
- passbook.oauth_client.source_types.discord
- passbook.oauth_client.source_types.facebook
- passbook.oauth_client.source_types.github
- passbook.oauth_client.source_types.google
- passbook.oauth_client.source_types.reddit
- passbook.oauth_client.source_types.supervisr
- passbook.oauth_client.source_types.twitter
saml_idp:
# 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,6 @@
apiVersion: v1 apiVersion: v1
appVersion: "0.1.12-beta" appVersion: "0.1.16-beta"
description: A Helm chart for passbook. description: A Helm chart for passbook.
name: passbook name: passbook
version: "0.1.12-beta" version: "0.1.16-beta"
icon: https://passbook.beryju.org/images/logo.png icon: https://passbook.beryju.org/images/logo.png

Binary file not shown.

Binary file not shown.

View File

@ -1,9 +1,9 @@
dependencies: dependencies:
- name: redis - name: rabbitmq
repository: https://kubernetes-charts.storage.googleapis.com/ repository: https://kubernetes-charts.storage.googleapis.com/
version: 5.1.0 version: 4.3.2
- name: postgresql - name: postgresql
repository: https://kubernetes-charts.storage.googleapis.com/ repository: https://kubernetes-charts.storage.googleapis.com/
version: 3.10.1 version: 3.10.1
digest: sha256:04bd136761f070e94a2ff32ff48ff87f5e07fbd451e5fd7f65551e3bd4680e5e digest: sha256:c36e054785f7d706d7d3f525eb1b167dbc89b42f84da7fc167a18bbb6542c999
generated: 2019-02-08T12:08:49.090666+01:00 generated: 2019-03-11T20:36:35.125079+01:00

View File

@ -1,6 +1,6 @@
dependencies: dependencies:
- name: redis - name: rabbitmq
version: 5.1.0 version: 4.3.2
repository: https://kubernetes-charts.storage.googleapis.com/ repository: https://kubernetes-charts.storage.googleapis.com/
- name: postgresql - name: postgresql
version: 3.10.1 version: 3.10.1

View File

@ -22,7 +22,7 @@ data:
host: 127.0.0.1 host: 127.0.0.1
port: 514 port: 514
email: email:
host: localhost host: {{ .Values.config.email.host }}
port: 25 port: 25
user: '' user: ''
password: '' password: ''
@ -36,7 +36,7 @@ data:
debug: false debug: false
secure_proxy_header: secure_proxy_header:
HTTP_X_FORWARDED_PROTO: https HTTP_X_FORWARDED_PROTO: https
redis: ":{{ .Values.redis.password }}@{{ .Release.Name }}-redis-master" rabbitmq: "user:{{ .Values.rabbitmq.rabbitmq.password }}@{{ .Release.Name }}-rabbitmq"
# Error reporting, sends stacktrace to sentry.services.beryju.org # Error reporting, sends stacktrace to sentry.services.beryju.org
error_report_enabled: {{ .Values.config.error_reporting }} error_report_enabled: {{ .Values.config.error_reporting }}

View File

@ -5,7 +5,7 @@
replicaCount: 1 replicaCount: 1
image: image:
tag: 0.1.12-beta tag: 0.1.16-beta
nameOverride: "" nameOverride: ""
@ -14,11 +14,17 @@ config:
# secret_key: _k*@6h2u2@q-dku57hhgzb7tnx*ba9wodcb^s9g0j59@=y(@_o # secret_key: _k*@6h2u2@q-dku57hhgzb7tnx*ba9wodcb^s9g0j59@=y(@_o
# Enable error reporting # Enable error reporting
error_reporting: true error_reporting: true
email:
host: localhost
postgresql: postgresql:
postgresqlDatabase: passbook postgresqlDatabase: passbook
postgresqlPassword: foo postgresqlPassword: foo
rabbitmq:
rabbitmq:
password: foo
service: service:
type: ClusterIP type: ClusterIP
port: 80 port: 80
@ -31,7 +37,6 @@ ingress:
path: / path: /
hosts: hosts:
- passbook.k8s.local - passbook.k8s.local
- kubernetes-healthcheck-host
defaultHost: passbook.k8s.local defaultHost: passbook.k8s.local
tls: [] tls: []
# - secretName: chart-example-tls # - secretName: chart-example-tls

View File

@ -1,2 +1,2 @@
"""passbook""" """passbook"""
__version__ = '0.1.12-beta' __version__ = '0.1.16-beta'

View File

@ -1,2 +1,2 @@
"""passbook admin""" """passbook admin"""
__version__ = '0.1.12-beta' __version__ = '0.1.16-beta'

View File

@ -1,2 +1,2 @@
"""passbook api""" """passbook api"""
__version__ = '0.1.12-beta' __version__ = '0.1.16-beta'

View File

@ -1,2 +1,2 @@
"""passbook audit Header""" """passbook audit Header"""
__version__ = '0.1.12-beta' __version__ = '0.1.16-beta'

View File

@ -1,2 +1,2 @@
"""passbook captcha_factor Header""" """passbook captcha_factor Header"""
__version__ = '0.1.12-beta' __version__ = '0.1.16-beta'

View File

@ -1,2 +1,2 @@
"""passbook core""" """passbook core"""
__version__ = '0.1.12-beta' __version__ = '0.1.16-beta'

View File

@ -12,6 +12,8 @@ LOGGER = getLogger(__name__)
@CELERY_APP.task() @CELERY_APP.task()
def _policy_engine_task(user_pk, policy_pk, **kwargs): def _policy_engine_task(user_pk, policy_pk, **kwargs):
"""Task wrapper to run policy checking""" """Task wrapper to run policy checking"""
if not user_pk:
raise ValueError()
policy_obj = Policy.objects.filter(pk=policy_pk).select_subclasses().first() policy_obj = Policy.objects.filter(pk=policy_pk).select_subclasses().first()
user_obj = User.objects.get(pk=user_pk) user_obj = User.objects.get(pk=user_pk)
for key, value in kwargs.items(): for key, value in kwargs.items():
@ -73,7 +75,12 @@ class PolicyEngine:
def result(self): def result(self):
"""Get policy-checking result""" """Get policy-checking result"""
messages = [] messages = []
for policy_action, policy_result, policy_message in self._group.get(): try:
# ValueError can be thrown from _policy_engine_task when user is None
group_result = self._group.get()
except ValueError as exc:
return False, str(exc)
for policy_action, policy_result, policy_message in group_result:
passing = (policy_action == Policy.ACTION_ALLOW and policy_result) or \ passing = (policy_action == Policy.ACTION_ALLOW and policy_result) or \
(policy_action == Policy.ACTION_DENY and not policy_result) (policy_action == Policy.ACTION_DENY and not policy_result)
LOGGER.debug('Action=%s, Result=%r => %r', policy_action, policy_result, passing) LOGGER.debug('Action=%s, Result=%r => %r', policy_action, policy_result, passing)

View File

@ -7,7 +7,6 @@ raven
markdown markdown
colorlog colorlog
celery celery
redis
psycopg2 psycopg2
idna<2.8,>=2.5 idna<2.8,>=2.5
cherrypy cherrypy

View File

@ -184,8 +184,9 @@ CELERY_TIMEZONE = TIME_ZONE
CELERY_BEAT_SCHEDULE = {} CELERY_BEAT_SCHEDULE = {}
CELERY_CREATE_MISSING_QUEUES = True CELERY_CREATE_MISSING_QUEUES = True
CELERY_TASK_DEFAULT_QUEUE = 'passbook' CELERY_TASK_DEFAULT_QUEUE = 'passbook'
CELERY_BROKER_URL = 'redis://%s' % CONFIG.get('redis') CELERY_BROKER_URL = 'amqp://%s' % CONFIG.get('rabbitmq')
CELERY_RESULT_BACKEND = 'redis://%s' % CONFIG.get('redis') CELERY_RESULT_BACKEND = 'rpc://'
CELERY_ACKS_LATE = True
# Raven settings # Raven settings
RAVEN_CONFIG = { RAVEN_CONFIG = {

View File

@ -1,7 +1,10 @@
"""passbook util view tests""" """passbook util view tests"""
import string
from random import SystemRandom
from django.test import RequestFactory, TestCase from django.test import RequestFactory, TestCase
from passbook.core.models import User
from passbook.core.views.utils import LoadingView, PermissionDeniedView from passbook.core.views.utils import LoadingView, PermissionDeniedView
@ -9,6 +12,11 @@ class TestUtilViews(TestCase):
"""Test Utility Views""" """Test Utility Views"""
def setUp(self): def setUp(self):
self.user = User.objects.create_superuser(
username='unittest user',
email='unittest@example.com',
password=''.join(SystemRandom().choice(
string.ascii_uppercase + string.digits) for _ in range(8)))
self.factory = RequestFactory() self.factory = RequestFactory()
def test_loading_view(self): def test_loading_view(self):
@ -21,5 +29,6 @@ class TestUtilViews(TestCase):
def test_permission_denied_view(self): def test_permission_denied_view(self):
"""Test PermissionDeniedView""" """Test PermissionDeniedView"""
request = self.factory.get('something') request = self.factory.get('something')
request.user = self.user
response = PermissionDeniedView.as_view()(request) response = PermissionDeniedView.as_view()(request)
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)

View File

@ -1,6 +1,7 @@
"""passbook core user views""" """passbook core user views"""
from django.contrib import messages from django.contrib import messages
from django.contrib.auth import logout, update_session_auth_hash from django.contrib.auth import logout, update_session_auth_hash
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.messages.views import SuccessMessageMixin from django.contrib.messages.views import SuccessMessageMixin
from django.forms.utils import ErrorList from django.forms.utils import ErrorList
from django.shortcuts import redirect, reverse from django.shortcuts import redirect, reverse
@ -13,7 +14,7 @@ from passbook.core.forms.users import PasswordChangeForm, UserDetailForm
from passbook.lib.config import CONFIG from passbook.lib.config import CONFIG
class UserSettingsView(SuccessMessageMixin, UpdateView): class UserSettingsView(SuccessMessageMixin, LoginRequiredMixin, UpdateView):
"""Update User settings""" """Update User settings"""
template_name = 'user/settings.html' template_name = 'user/settings.html'
@ -25,7 +26,8 @@ class UserSettingsView(SuccessMessageMixin, UpdateView):
def get_object(self): def get_object(self):
return self.request.user return self.request.user
class UserDeleteView(DeleteView):
class UserDeleteView(LoginRequiredMixin, DeleteView):
"""Delete user account""" """Delete user account"""
template_name = 'generic/delete.html' template_name = 'generic/delete.html'
@ -38,7 +40,8 @@ class UserDeleteView(DeleteView):
logout(self.request) logout(self.request)
return reverse('passbook_core:auth-login') return reverse('passbook_core:auth-login')
class UserChangePasswordView(FormView):
class UserChangePasswordView(LoginRequiredMixin, FormView):
"""View for users to update their password""" """View for users to update their password"""
form_class = PasswordChangeForm form_class = PasswordChangeForm

View File

@ -1,5 +1,5 @@
"""passbook core utils view""" """passbook core utils view"""
from django.contrib.auth.mixins import LoginRequiredMixin
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.views.generic import TemplateView from django.views.generic import TemplateView
@ -21,7 +21,7 @@ class LoadingView(TemplateView):
kwargs['target_url'] = self.get_url() kwargs['target_url'] = self.get_url()
return super().get_context_data(**kwargs) return super().get_context_data(**kwargs)
class PermissionDeniedView(TemplateView): class PermissionDeniedView(LoginRequiredMixin, TemplateView):
"""Generic Permission denied view""" """Generic Permission denied view"""
template_name = 'login/denied.html' template_name = 'login/denied.html'

View File

@ -1,2 +1,2 @@
"""passbook hibp_policy""" """passbook hibp_policy"""
__version__ = '0.1.12-beta' __version__ = '0.1.16-beta'

View File

@ -1,2 +1,2 @@
"""Passbook ldap app Header""" """Passbook ldap app Header"""
__version__ = '0.1.12-beta' __version__ = '0.1.16-beta'

View File

@ -1,2 +1,2 @@
"""passbook lib""" """passbook lib"""
__version__ = '0.1.12-beta' __version__ = '0.1.16-beta'

View File

@ -29,7 +29,7 @@ web:
debug: false debug: false
secure_proxy_header: secure_proxy_header:
HTTP_X_FORWARDED_PROTO: https HTTP_X_FORWARDED_PROTO: https
redis: localhost rabbitmq: guest:guest@localhost/passbook
# Error reporting, sends stacktrace to sentry.services.beryju.org # Error reporting, sends stacktrace to sentry.services.beryju.org
error_report_enabled: true error_report_enabled: true
secret_key: 9$@r!d^1^jrn#fk#1#@ks#9&i$^s#1)_13%$rwjrhd=e8jfi_s secret_key: 9$@r!d^1^jrn#fk#1#@ks#9&i$^s#1)_13%$rwjrhd=e8jfi_s
@ -62,11 +62,6 @@ passbook:
uid_fields: uid_fields:
- username - username
- email - email
# Factors to load
factors:
- passbook.core.auth.factors.backend
- passbook.core.auth.factors.dummy
- passbook.captcha_factor.factor
session: session:
remember_age: 2592000 # 60 * 60 * 24 * 30, one month remember_age: 2592000 # 60 * 60 * 24 * 30, one month
# Provider-specific settings # Provider-specific settings

View File

@ -1,2 +1,2 @@
"""passbook oauth_client Header""" """passbook oauth_client Header"""
__version__ = '0.1.12-beta' __version__ = '0.1.16-beta'

View File

@ -1,2 +1,2 @@
"""passbook oauth_provider Header""" """passbook oauth_provider Header"""
__version__ = '0.1.12-beta' __version__ = '0.1.16-beta'

View File

@ -1,2 +1,2 @@
"""passbook otp Header""" """passbook otp Header"""
__version__ = '0.1.12-beta' __version__ = '0.1.16-beta'

View File

@ -1,2 +1,2 @@
"""passbook password_expiry""" """passbook password_expiry"""
__version__ = '0.1.12-beta' __version__ = '0.1.16-beta'

View File

@ -1,2 +1,2 @@
"""passbook saml_idp Header""" """passbook saml_idp Header"""
__version__ = '0.1.12-beta' __version__ = '0.1.16-beta'