Migrate to AutoSecretKey

Implement OIDC login
This commit is contained in:
Kumi 2022-10-25 14:40:48 +00:00
parent ac18f31d9a
commit 2ff91abe82
8 changed files with 171 additions and 69 deletions

1
.gitignore vendored
View file

@ -4,3 +4,4 @@ db.sqlite3
migrations/
venv/
localsettings.py
settings.ini

View file

@ -0,0 +1,13 @@
from django import template
from django.conf import settings
register = template.Library()
@register.simple_tag
def use_oidc():
return settings.USE_OIDC
@register.simple_tag
def oidc_provider():
return settings.OIDC_PROVIDER_NAME

View file

@ -1,4 +1,5 @@
{% extends "registration/base.html" %}
{% load oidc %}
{% block content %}
<div class="p-5">
@ -19,7 +20,13 @@
<button type="submit" class="btn btn-primary btn-user btn-block">
Login
</button>
<hr>
{% use_oidc as use_oidc %}
{% if use_oidc %}
<div style="text-align: center;">or</div>
<a href="{% url 'oidc_authentication_init' %}" class="btn btn-success btn-user btn-block">
Login via {% oidc_provider %}
</a>
{% endif %}
</form>
<hr>
<div class="text-center">

View file

@ -1,19 +1,28 @@
# You shouldn't have to change anything in here, ever.
# Use localsettings.py in the project's root directory instead.
# Use settings.ini in the project's root directory instead.
# If you make any changes in here, you may have trouble updating your Kumify installation.
from pathlib import Path
from localsettings import *
from autosecretkey import AutoSecretKey
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
CONFIG_FILE = AutoSecretKey(BASE_DIR / "settings.ini")
SECRET_KEY = CONFIG_FILE.secret_key
DEBUG = CONFIG_FILE.config.getboolean("KUMIFY", "Debug", fallback=False)
ALLOWED_HOSTS = [CONFIG_FILE.config.get("KUMIFY", "Host")]
CSRF_TRUSTED_ORIGINS = [f"https://{ALLOWED_HOSTS[0]}"]
TIME_ZONE = CONFIG_FILE.config.get("KUMIFY", "TimeZone", fallback="UTC")
# Application definition
try:
ENABLED_MODULES
ENABLED_MODULES # TODO: Move this to settings.ini
except NameError:
ENABLED_MODULES = [
'cbt',
@ -42,6 +51,7 @@ INSTALLED_APPS = [
'colorfield',
'multiselectfield',
'dbsettings',
'mozilla_django_oidc',
] + CORE_MODULES + ENABLED_MODULES
MIDDLEWARE = [
@ -76,30 +86,40 @@ WSGI_APPLICATION = 'kumify.wsgi.application'
# Database
# https://docs.djangoproject.com/en/3.1/ref/settings/#databases
# https://docs.djangoproject.com/en/4.0/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.contrib.gis.db.backends.spatialite',
'NAME': BASE_DIR / 'db.sqlite3',
} if not DB_HOST else {
'ENGINE': 'django.contrib.gis.db.backends.mysql',
'NAME': DB_NAME,
'USER': DB_USER,
'PASSWORD': DB_PASS,
'HOST': DB_HOST,
'PORT': DB_PORT,
'OPTIONS': {
'charset': 'utf8mb4',
'sql_mode': 'traditional',
if "MySQL" in CONFIG_FILE.config:
DATABASES = {
'default': {
'ENGINE': 'django.contrib.gis.db.backends.mysql',
'NAME': CONFIG_FILE.config.get("MySQL", "Database"),
'USER': CONFIG_FILE.config.get("MySQL", "Username"),
'PASSWORD': CONFIG_FILE.config.get("MySQL", "Password"),
'HOST': CONFIG_FILE.config.get("MySQL", "Host", fallback="localhost"),
'PORT': CONFIG_FILE.config.getint("MySQL", "Port", fallback=3306),
'OPTIONS': {
'charset': 'utf8mb4',
'sql_mode': 'traditional',
}
}
}
else:
DATABASES = {
'default': {
'ENGINE': 'django.contrib.gis.db.backends.spatialite',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
}
# Password validation
# https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators
AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend',
]
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
@ -135,15 +155,48 @@ USE_TZ = True
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.1/howto/static-files/
# https://docs.djangoproject.com/en/4.0/howto/static-files/
STATIC_URL = '/static/'
STATIC_ROOT = None if DEBUG else STATIC_ROOT
STATIC_ROOT = None if DEBUG else CONFIG_FILE.config.get("KUMIFY", "StaticRoot", fallback=BASE_DIR / "static")
LOGIN_REDIRECT_URL = '/'
LOGOUT_REDIRECT_URL = "/"
DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage' if not AWS_ACCESS_KEY_ID else 'storages.backends.s3boto3.S3Boto3Storage'
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3StaticStorage' if AWS_ACCESS_KEY_ID else 'django.contrib.staticfiles.storage.StaticFilesStorage'
if "S3" in CONFIG_FILE.config:
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3StaticStorage'
AWS_ACCESS_KEY_ID = CONFIG_FILE.config.get("S3", "AccessKey")
AWS_SECRET_ACCESS_KEY = CONFIG_FILE.config.get("S3", "SecretKey")
AWS_STORAGE_BUCKET_NAME = CONFIG_FILE.config.get("S3", "Bucket")
AWS_S3_ENDPOINT_URL = CONFIG_FILE.config.get("S3", "Endpoint")
# OpenID Connect
# https://mozilla-django-oidc.readthedocs.io/
USE_OIDC = False
if "OIDC" in CONFIG_FILE.config:
USE_OIDC = True
OIDC_PROVIDER_NAME = CONFIG_FILE.config.get("OIDC", "ProviderName", fallback="OpenID Connect")
AUTHENTICATION_BACKENDS.append('mozilla_django_oidc.auth.OIDCAuthenticationBackend')
OIDC_RP_CLIENT_ID = CONFIG_FILE.config.get("OIDC", "ClientID")
OIDC_RP_CLIENT_SECRET = CONFIG_FILE.config.get("OIDC", "ClientSecret")
if (opsk := CONFIG_FILE.config.get("OIDC", "OPSignKey", fallback="")):
OIDC_RP_SIGN_ALGO = "RS256"
OIDC_RP_IDP_SIGN_KEY = opsk
elif (jwks := CONFIG_FILE.config.get("OIDC", "JWKSEndpoint", fallback="")):
OIDC_RP_SIGN_ALGO = "RS256"
OIDC_OP_JWKS_ENDPOINT = jwks
OIDC_OP_AUTHORIZATION_ENDPOINT = CONFIG_FILE.config.get("OIDC", "AuthorizationEndpoint")
OIDC_OP_TOKEN_ENDPOINT = CONFIG_FILE.config.get("OIDC", "TokenEndpoint")
OIDC_OP_USER_ENDPOINT = CONFIG_FILE.config.get("OIDC", "UserInfoEndpoint")

View file

@ -26,5 +26,6 @@ urlpatterns = [
path('cron/', include("cronhandler.urls", "cron")),
path('webhooks/telegram/', TelegramWebhookView.as_view()),
path('dreams/', include("dreams.urls", "dreams")),
path('gpslog/', include("gpslog.urls"))
path('gpslog/', include("gpslog.urls")),
path('oidc/', include('mozilla_django_oidc.urls')),
]

View file

@ -1,42 +0,0 @@
# The secret key must be a long random string.
# You may use the django.core.management.utils.get_random_secret_key() function to generate one, or just smash your keyboard real hard a few times.
SECRET_KEY = "longrandomstring"
# Putting the system in debug mode will give you a lot of output if an error occurs, but it potentially exposes sensitive information like passwords.
# Only set this to True if you really need to, especially if you are running a public instance.
DEBUG = False
# Specify the time zone you are in. This will affect the times displayed in the application.
TIME_ZONE = "Europe/Vienna"
# You may set this variable to a list of domain names that are allowed to be used to access your instance.
ALLOWED_HOSTS = ["*"] # Rationale: The application should be running behind a reverse proxy anyway if it's public - let that handle which hosts are allowed
# If you are using an external server to make your instance public, we need to store some static files somewhere.
# Enter the appropriate directory and make sure your webserver serves that location at /static/
STATIC_ROOT = '/var/www/html/static/'
# By default, all files, including uploads, are stored locally.
# You may use an S3 compatible storage instead in order to increase reliability and decrease disk usage.
# If AWS_ACCESS_KEY_ID is set to None, local storage will be used.
# See https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html for all options you can use here.
# (NB: Only options starting with "AWS_" are allowed here, the storage configuration will be handled automatically.)
AWS_ACCESS_KEY_ID = None
AWS_SECRET_ACCESS_KEY = None
AWS_STORAGE_BUCKET_NAME = None
AWS_S3_ENDPOINT_URL = None
# By default, this application uses a local sqlite3 database file. You can choose to use a MariaDB/MySQL database instead.
# If DB_HOST is set to None, the sqlite3 database will be used.
DB_HOST = None # Host name of the database server
DB_PORT = 3306 # Port of the database server - the default value usually works
DB_NAME = None # Name of the database to be used
DB_USER = None # User name to authenticate with
DB_PASS = None # Password to authenticate with

View file

@ -19,3 +19,4 @@ panel
scipy
channels
django-autosecretkey
mozilla-django-oidc

68
settings.dist.ini Normal file
View file

@ -0,0 +1,68 @@
[KUMIFY]
# Putting the system in debug mode will give you a lot of output if an error occurs, but it potentially exposes sensitive information like passwords.
# Only set this to 1 (= True) if you really need to, especially if you are running a public instance.
Debug = 0
# Specify the time zone you are in. This will affect the times displayed in the application.
TimeZone = Europe/Vienna
# Set this to the domain name you are using for Kumify
Host = kumify.lan
# If you are not using S3 storage (see below), we need to store your static files somewhere locally
# Enter the appropriate directory and make sure your webserver serves that location at /static/
# If unset, the "static" subdirectory of the Kumify base directory is going to be used
StaticRoot = '/var/www/html/static/'
# By default, all files, including uploads, are stored locally.
# You may use an S3 compatible storage instead in order to increase reliability and decrease local disk usage.
# If this section is commented out, local storage will be used.
# [S3]
# AccessKey = kumify
# SecretKey = !!!verysecret!!!
# Bucket = kumify
# Endpoint = https://minio.kumify.lan
# By default, this application uses a local sqlite3 database file. You can choose to use a MariaDB/MySQL database instead.
# If this section is commented out, the local sqlite3 database is used
# [MySQL]
# Database = kumify
# Username = kumify
# Password = secret123!
# Host = localhost
# Port = 3306
# By default, Kumify uses local user authentication only
# In order to allow users to authenticate using an OpenID Connect provider, comment in this section and set the values accordingly
# [OIDC]
# Optionally, enter the name of the OIDC provider, so it can be displayed on buttons
# ProviderName = OpenID Connect
# ClientID = Your client ID
# ClientSecret = Your client secret
# To use the RS256 algorihm, set one of the following two settings
# OPSignKey = OP signing key in PEM or DER format
# JWKSEndpoint = https://kumidc.lan/openid/jwks
# These URLs need to correspond to your ID provider
# AuthorizationEndpoint = https://kumidc.lan/openid/authorize
# TokenEndpoint = https://kumidc.lan/openid/token
# UserInfoEndpoint = https://kumidc.lan/openid/userinfo
# If you want to allow users who do not yet have a Kumify account to log in using the OIDC provider, uncomment the following setting and set it to 1.
# CreateUsers = 0