From fa28fd436ef03b66c270ad460cadfd877434fd0d Mon Sep 17 00:00:00 2001 From: Jon Date: Thu, 6 Jun 2024 07:27:51 +0930 Subject: [PATCH 001/111] ci: dont rebuild on dev on git tag !19 --- .gitlab-ci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1984159d..58b48d4c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -73,6 +73,12 @@ Docker Container: # - '{dockerfile,dockerfile.j2}' # when: always + - if: + $CI_COMMIT_AUTHOR =='nfc_bot ' + && + $CI_COMMIT_BRANCH == "development" + when: never + - if: # condition_not_master_or_dev_push $CI_COMMIT_BRANCH != "master" && $CI_COMMIT_BRANCH != "development" && From 3040d4afe74c65ebf656329ea3cfe13e59409a61 Mon Sep 17 00:00:00 2001 From: Jon Date: Fri, 7 Jun 2024 18:56:20 +0930 Subject: [PATCH 002/111] feat(base): configurable SSO !20 #1 --- app/app/context_processors/base.py | 29 ++++++++++ app/app/settings.py | 32 ++++++++++- app/app/urls.py | 12 ++++- app/templates/registration/login.html | 5 ++ .../projects/django-template/configuration.md | 53 +++++++++++++++++++ mkdocs.yml | 2 + 6 files changed, 130 insertions(+), 3 deletions(-) create mode 100644 docs/projects/django-template/configuration.md diff --git a/app/app/context_processors/base.py b/app/app/context_processors/base.py index 6a23f19d..b1bc1e86 100644 --- a/app/app/context_processors/base.py +++ b/app/app/context_processors/base.py @@ -21,6 +21,34 @@ def request(request): return request.get_full_path() +def social_backends(request): + """ Fetch Backend Names + + Required for use on the login page to dynamically build the social auth URLS + + Returns: + list(str): backend name + """ + from importlib import import_module + + social_backends = [] + + if hasattr(settings, 'SSO_BACKENDS'): + + for backend in settings.SSO_BACKENDS: + + paths = str(backend).split('.') + + module = import_module(paths[0] + '.' + paths[1] + '.' + paths[2]) + + backend_class = getattr(module, paths[3]) + backend = backend_class.name + + social_backends += [ str(backend) ] + + return social_backends + + def user_settings(context) -> int: """ Provides the settings ID for the current user. @@ -136,5 +164,6 @@ def common(context): return { 'build_details': build_details(context), 'nav_items': nav_items(context), + 'social_backends': social_backends(context), 'user_settings': user_settings(context), } diff --git a/app/app/settings.py b/app/app/settings.py index 0f4d2922..78584deb 100644 --- a/app/app/settings.py +++ b/app/app/settings.py @@ -30,8 +30,11 @@ BUILD_VERSION = os.getenv('CI_COMMIT_TAG') # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = 'django-insecure-b*41-$afq0yl)1e#qpz^-nbt-opvjwb#avv++b9rfdxa@b55sk' -# SECURITY WARNING: don't run with debug turned on in production! -DEBUG = False +# +# Defaults +# +DEBUG = False # SECURITY WARNING: don't run with debug turned on in production! +SSO_ENABLED = False # Enable SSO ALLOWED_HOSTS = [ '*' ] @@ -226,6 +229,12 @@ if os.path.isdir(SETTINGS_DIR): settings_files = os.path.join(SETTINGS_DIR, '*.py') include(optional(settings_files)) +# +# Settings to reset to prevent user from over-riding +# +AUTHENTICATION_BACKENDS = ( + 'django.contrib.auth.backends.ModelBackend', +) if DEBUG: INSTALLED_APPS += [ @@ -245,3 +254,22 @@ if DEBUG: 'information.apps.InformationConfig', 'project_management.apps.ProjectManagementConfig', ] + + +if SSO_ENABLED: + + AUTHENTICATION_BACKENDS += ( + *SSO_BACKENDS, + ) + + SOCIAL_AUTH_PIPELINE = ( + 'social_core.pipeline.social_auth.social_details', + 'social_core.pipeline.social_auth.social_uid', + 'social_core.pipeline.social_auth.social_user', + 'social_core.pipeline.user.get_username', + 'social_core.pipeline.social_auth.associate_by_email', + 'social_core.pipeline.user.create_user', + 'social_core.pipeline.social_auth.associate_user', + 'social_core.pipeline.social_auth.load_extra_data', + 'social_core.pipeline.user.user_details', + ) diff --git a/app/app/urls.py b/app/app/urls.py index e59a6b7d..09a1292c 100644 --- a/app/app/urls.py +++ b/app/app/urls.py @@ -43,9 +43,18 @@ urlpatterns = [ path("config_management/", include("config_management.urls")), path("history//", history.View.as_view(), name='_history'), - re_path(r'^static/(?P.*)$', serve,{'document_root': settings.STATIC_ROOT}) + re_path(r'^static/(?P.*)$', serve,{'document_root': settings.STATIC_ROOT}), + ] + +if settings.SSO_ENABLED: + + urlpatterns += [ + path('sso/', include('social_django.urls', namespace='social')) + ] + + if settings.API_ENABLED: urlpatterns += [ @@ -54,6 +63,7 @@ if settings.API_ENABLED: path('api/swagger/', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'), ] + if settings.DEBUG: urlpatterns += [ diff --git a/app/templates/registration/login.html b/app/templates/registration/login.html index cc696e18..580e1e35 100644 --- a/app/templates/registration/login.html +++ b/app/templates/registration/login.html @@ -22,6 +22,11 @@
+ {% for backend in social_backends %} + + {{ backend }} + + {% endfor %} diff --git a/docs/projects/django-template/configuration.md b/docs/projects/django-template/configuration.md new file mode 100644 index 00000000..b8ea2073 --- /dev/null +++ b/docs/projects/django-template/configuration.md @@ -0,0 +1,53 @@ +--- +title: Configuring Django ITSM +description: No Fuss Computings Django ITSM Application Configuration +date: 2024-06-07 +template: project.html +about: https://gitlab.com/nofusscomputing/infrastructure/configuration-management/django_app +--- + +This page details the configuration for setting up the application. + + +## Single Sign-On + +- `SSO_ENABLED`, boolean + +Single Sign on (SSO) is made possible through the [social django application](https://python-social-auth.readthedocs.io/en/latest/configuration/django.html). Specific configuration for the backend that you would like to configure can be viewed within it's [documentation](https://python-social-auth.readthedocs.io/en/latest/backends/index.html). In most cases the only configuration will need to be done for the following attributes: `SSO_ENABLED`, `SSO_BACKENDS` and `SOCIAL_AUTH_`. + +!!! danger + Within the social django documentation, it will state the the configuration key for the backends is within attribute `AUTHENTICATION_BACKENDS`, don't use this attribute. Instead use attribute `SSO_BACKENDS` so as not to effect the authentication of the ITSM application. + + +### Example SSO Configuration + +Attributes with prefix `SSO_` are specifically for this application. + +``` py + +SSO_ENABLED = True # Optional, boolean. Enable SSO Authentication + +SSO_BACKENDS = ( # this attribute replaces `AUTHENTICATION_BACKENDS` and must be used instead of. + "social_core.backends.open_id_connect.OpenIdConnectAuth", +) + +# Example configuration for the openid connect backend +SOCIAL_AUTH_OIDC_OIDC_ENDPOINT = 'https:///realms/' +SOCIAL_AUTH_OIDC_KEY = '' +SOCIAL_AUTH_OIDC_SECRET = '' +# SOCIAL_AUTH_OIDC_SCOPE = ['groups'] +# SOCIAL_AUTH_OIDC_IGNORE_DEFAULT_SCOPE = True # default scopes: “openid”, “profile” and “email” + +``` + + +## Available Settings + +Below are the available configuration values along with their default value. + +``` py + +DEBUG = False # SECURITY WARNING: don't run with debug turned on in production! +SSO_ENABLED = False # Enable SSO + +``` diff --git a/mkdocs.yml b/mkdocs.yml index 7a83600b..709521f6 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -21,6 +21,8 @@ nav: - projects/django-template/index.md + - projects/django-template/configuration.md + - projects/django-template/api.md - projects/django-template/config_management/index.md From b38984fcb95ab121a610710b9df049ee7caa17cd Mon Sep 17 00:00:00 2001 From: Jon Date: Fri, 7 Jun 2024 19:33:57 +0930 Subject: [PATCH 003/111] feat(base): Enforceable SSO ONLY this setting removes the login form and forces a redirect to the SSO signin page. !20 #1 --- app/app/settings.py | 4 ++++ app/templates/registration/login.html | 12 +++++++++--- docs/projects/django-template/configuration.md | 4 +++- docs/projects/django-template/index.md | 2 +- 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/app/app/settings.py b/app/app/settings.py index 78584deb..afee205b 100644 --- a/app/app/settings.py +++ b/app/app/settings.py @@ -35,6 +35,7 @@ SECRET_KEY = 'django-insecure-b*41-$afq0yl)1e#qpz^-nbt-opvjwb#avv++b9rfdxa@b55sk # DEBUG = False # SECURITY WARNING: don't run with debug turned on in production! SSO_ENABLED = False # Enable SSO +SSO_LOGIN_ONLY_BACKEND = None # Use specified SSO backend as the ONLY method to login. (builting login form will not be used) ALLOWED_HOSTS = [ '*' ] @@ -258,6 +259,9 @@ if DEBUG: if SSO_ENABLED: + if SSO_LOGIN_ONLY_BACKEND: + LOGIN_URL = f'/sso/login/{SSO_LOGIN_ONLY_BACKEND}/' + AUTHENTICATION_BACKENDS += ( *SSO_BACKENDS, ) diff --git a/app/templates/registration/login.html b/app/templates/registration/login.html index 580e1e35..652850d9 100644 --- a/app/templates/registration/login.html +++ b/app/templates/registration/login.html @@ -1,3 +1,5 @@ +{% load settings_value %} +{% settings_value "SSO_LOGIN_ONLY_BACKEND" as SSO_LOGIN_ONLY_BACKEND %} @@ -6,14 +8,18 @@ + {% if SSO_LOGIN_ONLY_BACKEND %} + + {% else %} - + {% endif %} - + + {% if not SSO_LOGIN_ONLY_BACKEND %}
@@ -29,8 +35,8 @@ {% endfor %}
-
+ {% endif %} diff --git a/docs/projects/django-template/configuration.md b/docs/projects/django-template/configuration.md index b8ea2073..a6294adb 100644 --- a/docs/projects/django-template/configuration.md +++ b/docs/projects/django-template/configuration.md @@ -13,7 +13,7 @@ This page details the configuration for setting up the application. - `SSO_ENABLED`, boolean -Single Sign on (SSO) is made possible through the [social django application](https://python-social-auth.readthedocs.io/en/latest/configuration/django.html). Specific configuration for the backend that you would like to configure can be viewed within it's [documentation](https://python-social-auth.readthedocs.io/en/latest/backends/index.html). In most cases the only configuration will need to be done for the following attributes: `SSO_ENABLED`, `SSO_BACKENDS` and `SOCIAL_AUTH_`. +Single Sign on (SSO) is made possible through the [social django application](https://python-social-auth.readthedocs.io/en/latest/configuration/django.html). Specific configuration for the backend that you would like to configure can be viewed within it's [documentation](https://python-social-auth.readthedocs.io/en/latest/backends/index.html). In most cases the only configuration that will need to be defined are for the following attributes: `SSO_ENABLED`, optionally `SSO_BACKENDS` and those with prefix `SOCIAL_AUTH_`. !!! danger Within the social django documentation, it will state the the configuration key for the backends is within attribute `AUTHENTICATION_BACKENDS`, don't use this attribute. Instead use attribute `SSO_BACKENDS` so as not to effect the authentication of the ITSM application. @@ -27,6 +27,8 @@ Attributes with prefix `SSO_` are specifically for this application. SSO_ENABLED = True # Optional, boolean. Enable SSO Authentication +SSO_LOGIN_ONLY_BACKEND = 'oidc' # Optional, string. To only use SSO authentication, specify the backend name here + SSO_BACKENDS = ( # this attribute replaces `AUTHENTICATION_BACKENDS` and must be used instead of. "social_core.backends.open_id_connect.OpenIdConnectAuth", ) diff --git a/docs/projects/django-template/index.md b/docs/projects/django-template/index.md index ce1e09ca..da2377cf 100644 --- a/docs/projects/django-template/index.md +++ b/docs/projects/django-template/index.md @@ -52,7 +52,7 @@ Settings for the application are stored within a docker volume at path `/etc/its ### Settings file -The settings file is a python file `.py` and must remain a valid python file for the application to work. +The settings file is a python file `.py` and must remain a valid python file for the application to work. ``` py title="settings.py" From 95a08b2d2ca5915eb62abbcfe2acf45e85b578d3 Mon Sep 17 00:00:00 2001 From: Jon Date: Fri, 7 Jun 2024 20:01:56 +0930 Subject: [PATCH 004/111] refactor: adjust template block names renamed so they make sense !20 --- app/access/templates/access/index.html.j2 | 2 +- app/access/templates/access/organization.html.j2 | 2 +- app/access/templates/access/team.html.j2 | 2 +- .../templates/config_management/group.html.j2 | 2 +- .../config_management/group_index.html.j2 | 2 +- app/core/templates/history.html.j2 | 2 +- app/itam/templates/itam/device.html.j2 | 2 +- app/itam/templates/itam/device_index.html.j2 | 2 +- app/itam/templates/itam/operating_system.html.j2 | 2 +- .../templates/itam/operating_system_index.html.j2 | 2 +- app/itam/templates/itam/software.html.j2 | 2 +- app/itam/templates/itam/software_index.html.j2 | 2 +- .../templates/settings/device_models.html.j2 | 2 +- .../templates/settings/device_types.html.j2 | 2 +- app/settings/templates/settings/home.html.j2 | 2 +- .../templates/settings/manufacturers.html.j2 | 2 +- .../settings/software_categories.html.j2 | 2 +- app/templates/base.html.j2 | 15 +++++++-------- app/templates/form.html.j2 | 2 +- app/templates/home.html.j2 | 2 +- app/templates/password_change.html.j2 | 2 +- 21 files changed, 27 insertions(+), 28 deletions(-) diff --git a/app/access/templates/access/index.html.j2 b/app/access/templates/access/index.html.j2 index c11ba592..38679c58 100644 --- a/app/access/templates/access/index.html.j2 +++ b/app/access/templates/access/index.html.j2 @@ -3,7 +3,7 @@ {% block title %}Organizations{% endblock %} {% block content_header_icon %}{% endblock %} -{% block body%} +{% block content %} diff --git a/app/access/templates/access/organization.html.j2 b/app/access/templates/access/organization.html.j2 index d7e10b64..a2cfeac6 100644 --- a/app/access/templates/access/organization.html.j2 +++ b/app/access/templates/access/organization.html.j2 @@ -2,7 +2,7 @@ {% block title %}Organization - {{ organization.name }}{% endblock %} -{% block body%} +{% block content %}
diff --git a/app/access/templates/access/team.html.j2 b/app/access/templates/access/team.html.j2 index 0a2295ed..d5d7a5b4 100644 --- a/app/access/templates/access/team.html.j2 +++ b/app/access/templates/access/team.html.j2 @@ -2,7 +2,7 @@ {% block title %}Team - {{ team.team_name }}{% endblock %} -{% block body%} +{% block content %}
{% csrf_token %}
diff --git a/app/config_management/templates/config_management/group.html.j2 b/app/config_management/templates/config_management/group.html.j2 index 6594ea63..0c47956d 100644 --- a/app/config_management/templates/config_management/group.html.j2 +++ b/app/config_management/templates/config_management/group.html.j2 @@ -1,6 +1,6 @@ {% extends 'base.html.j2' %} -{% block body %} +{% block content %}