Skip to content

Commit

Permalink
Merge pull request #513 from GhostManager/feature/sso-json-and-file-api
Browse files Browse the repository at this point in the history
Release: SSO, JSON field types, and File Upload Mutations
  • Loading branch information
chrismaddalena authored Sep 23, 2024
2 parents 970d591 + f3fe783 commit cb7f13e
Show file tree
Hide file tree
Showing 89 changed files with 2,576 additions and 797 deletions.
1 change: 1 addition & 0 deletions .github/workflows/inactive-issues.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ jobs:
days-before-pr-stale: -1
days-before-pr-close: -1
repo-token: ${{ secrets.GITHUB_TOKEN }}
exempt-issue-labels: "enhancement, help wanted, question, in progress"
34 changes: 34 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,40 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

# CHANGELOG

## [4.3.0] – 23 Sep 2024

### Added

* Added two mutations to the GraphQL API to support uploading new evidence files and report template files (Closes #230)
* Added a new adapter for handling authentication for Single Sign-On (SSO) providers
* The adapter fills-in a nearly full profile for any new accounts (full name, email address, username)
* Usernames for new accounts will default to the first half of the email address
* If an existing account has the same email address, the accounts will be linked
* Review the wiki for more information: [https://www.ghostwriter.wiki/features/access-authentication-and-session-controls/single-sign-on](https://www.ghostwriter.wiki/features/access-authentication-and-session-controls/single-sign-on)
* Added support for loading customized config files
* These are files you can use to modify settings normally found in _/config/settings/base.py_ and _production.py_
* Admins can make changes to the custom config files without worrying about the changes needing to be stashed prior to pulling an update
* Review this section of the wiki for information: [https://www.ghostwriter.wiki/features/access-authentication-and-session-controls/single-sign-on#configuring-an-sso-provider](https://www.ghostwriter.wiki/features/access-authentication-and-session-controls/single-sign-on#configuring-an-sso-provider)
* Added support for a JSON field type for custom fields
* Added a "Tags" column to the domain and server library tables

### Changed

* Updated the `django-allauth` module used for authentication and SSO
* **Important:** This change impacts anyone currently using SSO with Azure
* The `azure` provider is now `microsoft` and SSO configurations will need to be updated
* Changed the cloud infrastructure monitoring task to also check auxiliary IP addresses when determining if a cloud host is tracked in a project
* Cloud hosts tracked on a project no longer require a unique IP address
* A warning is displayed if a cloud host is tracked on a project with multiple hosts sharing the same IP address
* Changed filtering on tags to be case-insensitive
* On the report dashboard, clicking an autocomplete suggestion for a finding or observation will now add the item to the report

### Fixed

* Fixed spaces disappearing after Microsoft Word cross-references placed at the beginning of a new line or paragraph

### [4.2.5] - 7 August 2024

### Changed
Expand Down
4 changes: 2 additions & 2 deletions VERSION
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
v4.2.5
9 August 2024
v4.3.0
23 September 2024
47 changes: 45 additions & 2 deletions config/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
# 3rd Party Libraries
import environ

__version__ = "4.2.5"
__version__ = "4.3.0"
VERSION = __version__
RELEASE_DATE = "9 August 2024"
RELEASE_DATE = "23 September 2024"

ROOT_DIR = Path(__file__).resolve(strict=True).parent.parent.parent
APPS_DIR = ROOT_DIR / "ghostwriter"
Expand Down Expand Up @@ -195,6 +195,7 @@
"django_otp.middleware.OTPMiddleware",
"allauth_2fa.middleware.AllauthTwoFactorMiddleware",
"ghostwriter.middleware.Require2FAMiddleware",
"allauth.account.middleware.AccountMiddleware",
]

# STATIC
Expand Down Expand Up @@ -321,6 +322,8 @@
# ------------------------------------------------------------------------------
ACCOUNT_ALLOW_REGISTRATION = env.bool("DJANGO_ACCOUNT_ALLOW_REGISTRATION", False)
SOCIAL_ACCOUNT_ALLOW_REGISTRATION = env.bool("DJANGO_SOCIAL_ACCOUNT_ALLOW_REGISTRATION", False)
SOCIAL_ACCOUNT_DOMAIN_ALLOWLIST = env("DJANGO_SOCIAL_ACCOUNT_DOMAIN_ALLOWLIST", default="")
SOCIALACCOUNT_LOGIN_ON_GET = env.bool("DJANGO_SOCIAL_ACCOUNT_LOGIN_ON_GET", False)
# https://django-allauth.readthedocs.io/en/latest/configuration.html
ACCOUNT_AUTHENTICATION_METHOD = "username"
# https://django-allauth.readthedocs.io/en/latest/configuration.html
Expand All @@ -334,6 +337,7 @@
ACCOUNT_SIGNUP_FORM_CLASS = "ghostwriter.home.forms.SignupForm"
ACCOUNT_FORMS = {
"login": "ghostwriter.users.forms.UserLoginForm",
"signup": "ghostwriter.users.forms.UserSignupForm",
}
ALLAUTH_2FA_FORMS = {
"authenticate": "ghostwriter.users.forms.User2FAAuthenticateForm",
Expand Down Expand Up @@ -497,3 +501,42 @@
# Tagging
# ------------------------------------------------------------------------------
TAGGIT_CASE_INSENSITIVE = True


def include_settings(py_glob):
"""
Includes a glob of Python settings files.
The files will be sorted alphabetically.
"""
import sys
import os
import glob
from importlib.util import module_from_spec, spec_from_file_location

# Get caller's global scope
scope = sys._getframe(1).f_globals

including_path = scope["__file__"].rstrip("c")
including_dir = os.path.dirname(including_path)
py_glob_rel = os.path.join(including_dir, py_glob)

for relpath in sorted(glob.glob(py_glob_rel)):
# Read and execute files
with open(relpath, "rb") as f:
contents = f.read()
compiled = compile(contents, relpath, "exec")
# Use of `exec` is typically dangerous, but we're only executing our own settings files
# The settings files are user controlled, but any danger represented by executing them also applies to executing the main settings files
# The primary concern is an admin could unwittingly execute a malicious settings file they did not realize was present
# However, an admin could also unwittingly run a malicious command in the main settings file
exec(compiled, scope)

# Adds dummy module to sys.modules so runserver will reload if they change
rel_path = os.path.relpath(including_path)
module_name = "_settings_include.{0}".format(
rel_path[: rel_path.rfind(".")].replace("/", "."),
)

spec = spec_from_file_location(module_name, including_path)
module = module_from_spec(spec)
sys.modules[module_name] = module
2 changes: 2 additions & 0 deletions config/settings/local.d/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/*
!/.gitignore
14 changes: 7 additions & 7 deletions config/settings/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@
default="Vso7i8BApwA6km4L50PFRvqcTtGZHLrC1pnKLCXqfTWifhjbGq4nTd6ZrDH2Iobe",
)
# https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts
hosts = env(
"DJANGO_ALLOWED_HOSTS",
default="localhost 0.0.0.0 127.0.0.1 172.20.0.5 django host.docker.internal"
)
hosts = env("DJANGO_ALLOWED_HOSTS", default="localhost 0.0.0.0 127.0.0.1 172.20.0.5 django host.docker.internal")
ALLOWED_HOSTS = hosts.split(" ")

# CACHES
Expand All @@ -30,9 +27,7 @@
# EMAIL
# ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#email-backend
EMAIL_BACKEND = env(
"DJANGO_EMAIL_BACKEND", default="django.core.mail.backends.console.EmailBackend"
)
EMAIL_BACKEND = env("DJANGO_EMAIL_BACKEND", default="django.core.mail.backends.console.EmailBackend")
# https://docs.djangoproject.com/en/dev/ref/settings/#email-host
EMAIL_HOST = "localhost"
# https://docs.djangoproject.com/en/dev/ref/settings/#email-port
Expand Down Expand Up @@ -70,3 +65,8 @@
# LOGGING.setdefault("loggers", {})["django.db.backends"] = {
# "level": "DEBUG"
# }

# Include files in `local.d`. These are added in alphabetical order - using a numeric prefix
# like `10-subconfig.py` can be used to order inclusions

include_settings("./local.d/*.py")
2 changes: 2 additions & 0 deletions config/settings/production.d/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/*
!/.gitignore
27 changes: 10 additions & 17 deletions config/settings/production.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@
# https://docs.djangoproject.com/en/dev/ref/settings/#secret-key
SECRET_KEY = env("DJANGO_SECRET_KEY")
# https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts
hosts = env(
"DJANGO_ALLOWED_HOSTS",
default="ghostwriter.local localhost host.docker.internal"
)
hosts = env("DJANGO_ALLOWED_HOSTS", default="ghostwriter.local localhost host.docker.internal")
ALLOWED_HOSTS = hosts.split(" ")

# DATABASES
Expand Down Expand Up @@ -48,9 +45,7 @@
# TODO: set this to 60 seconds first and then to 518400 once you prove the former works
SECURE_HSTS_SECONDS = 60
# https://docs.djangoproject.com/en/dev/ref/settings/#secure-hsts-include-subdomains
SECURE_HSTS_INCLUDE_SUBDOMAINS = env.bool(
"DJANGO_SECURE_HSTS_INCLUDE_SUBDOMAINS", default=True
)
SECURE_HSTS_INCLUDE_SUBDOMAINS = env.bool("DJANGO_SECURE_HSTS_INCLUDE_SUBDOMAINS", default=True)
# https://docs.djangoproject.com/en/dev/ref/settings/#secure-hsts-preload
SECURE_HSTS_PRELOAD = env.bool("DJANGO_SECURE_HSTS_PRELOAD", default=True)
# https://docs.djangoproject.com/en/dev/ref/middleware/#x-content-type-options-nosniff
Expand All @@ -75,9 +70,7 @@
# EMAIL
# ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#default-from-email
DEFAULT_FROM_EMAIL = env(
"DJANGO_DEFAULT_FROM_EMAIL", default="Ghostwriter <[email protected]>"
)
DEFAULT_FROM_EMAIL = env("DJANGO_DEFAULT_FROM_EMAIL", default="Ghostwriter <[email protected]>")
# https://docs.djangoproject.com/en/dev/ref/settings/#server-email
SERVER_EMAIL = env("DJANGO_SERVER_EMAIL", default=DEFAULT_FROM_EMAIL)
# https://docs.djangoproject.com/en/dev/ref/settings/#email-subject-prefix
Expand All @@ -92,7 +85,7 @@
# ------------------------------------------------------------------------------
# https://anymail.readthedocs.io/en/stable/installation/#installing-anymail
INSTALLED_APPS += ["anymail"] # noqa F405
EMAIL_BACKEND = "anymail.backends.mailgun.EmailBackend"
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
# https://anymail.readthedocs.io/en/stable/installation/#anymail-settings-reference
ANYMAIL = {
"MAILGUN_API_KEY": env("MAILGUN_API_KEY"),
Expand Down Expand Up @@ -127,12 +120,7 @@
"version": 1,
"disable_existing_loggers": False,
"filters": {"require_debug_false": {"()": "django.utils.log.RequireDebugFalse"}},
"formatters": {
"verbose": {
"format": "%(levelname)s %(asctime)s %(module)s "
"%(process)d %(thread)d %(message)s"
}
},
"formatters": {"verbose": {"format": "%(levelname)s %(asctime)s %(module)s " "%(process)d %(thread)d %(message)s"}},
"handlers": {
"mail_admins": {
"level": "ERROR",
Expand Down Expand Up @@ -162,3 +150,8 @@

# Your stuff...
# ------------------------------------------------------------------------------

# Include files in `production.d`. These are added in alphabetical order - using a numeric prefix
# like `10-subconfig.py` can be used to order inclusions

include_settings("./production.d/*.py")
Binary file modified ghostwriter-cli-linux
Binary file not shown.
Binary file modified ghostwriter-cli-macos
Binary file not shown.
Binary file modified ghostwriter-cli.exe
Binary file not shown.
Loading

0 comments on commit cb7f13e

Please sign in to comment.