Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions config/api_router.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
from rest_framework.routers import DefaultRouter

from scram.route_manager.api.views import (
ActionTypeViewSet,
ClientViewSet,
EntryViewSet,
IgnoreEntryViewSet,
)
from scram.route_manager.api.views import ActionTypeViewSet, ClientViewSet, EntryViewSet, IgnoreEntryViewSet
from scram.users.api.views import UserViewSet

router = DefaultRouter()
Expand Down
1 change: 1 addition & 0 deletions config/asgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

# TODO: from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter

# TODO: from channels.security.websocket import AllowedHostsOriginValidator
from django.core.asgi import get_asgi_application

Expand Down
19 changes: 10 additions & 9 deletions config/consumers.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ async def connect(self):
# TODO: Filter by our actiontype

# Avoid lazy evaluation
routes = await sync_to_async(list)(Entry.objects.filter(is_active=True).values_list('route__route', flat=True))
routes = await sync_to_async(list)(Entry.objects.filter(is_active=True).values_list("route__route", flat=True))
for route in routes:
await self.send_json({"type": "translator_add", "message": {"route": str(route)}})

Expand All @@ -24,10 +24,10 @@ async def disconnect(self, close_code):

async def receive_json(self, content):
"""Received a WebSocket message"""
if content['type'] == 'translator_check_resp':
if content["type"] == "translator_check_resp":
# We received a check response from a translator, forward to web UI.
channel = content.pop('channel')
content['type'] = 'wui_check_resp'
channel = content.pop("channel")
content["type"] = "wui_check_resp"
await self.channel_layer.send(channel, content)

async def _send_event(self, event):
Expand All @@ -50,14 +50,15 @@ async def connect(self):

# Receive message from WebSocket
async def receive_json(self, content):
if content['type'] == 'wui_check_req':
if content["type"] == "wui_check_req":
# Web UI asks us to check; forward to translator(s)
await self.channel_layer.group_send(
self.translator_group,
{"type": "translator_check",
"channel": self.channel_name,
"message": content['message'],
},
{
"type": "translator_check",
"channel": self.channel_name,
"message": content["message"],
},
)

async def wui_check_resp(self, event):
Expand Down
6 changes: 2 additions & 4 deletions config/routing.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
from . import consumers

websocket_urlpatterns = [
re_path(r"ws/route_manager/translator_(?P<actiontype>\w+)/$",
consumers.TranslatorConsumer.as_asgi()),
re_path(r"ws/route_manager/webui_(?P<actiontype>\w+)/$",
consumers.WebUIConsumer.as_asgi()),
re_path(r"ws/route_manager/translator_(?P<actiontype>\w+)/$", consumers.TranslatorConsumer.as_asgi()),
re_path(r"ws/route_manager/webui_(?P<actiontype>\w+)/$", consumers.WebUIConsumer.as_asgi()),
]
20 changes: 4 additions & 16 deletions config/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,7 @@
]
# https://docs.djangoproject.com/en/dev/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator"
},
{"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator"},
{"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator"},
{"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator"},
{"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator"},
Expand Down Expand Up @@ -222,9 +220,7 @@
# EMAIL
# ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#email-backend
EMAIL_BACKEND = env(
"DJANGO_EMAIL_BACKEND", default="django.core.mail.backends.smtp.EmailBackend"
)
EMAIL_BACKEND = env("DJANGO_EMAIL_BACKEND", default="django.core.mail.backends.smtp.EmailBackend")
# https://docs.djangoproject.com/en/dev/ref/settings/#email-timeout
EMAIL_TIMEOUT = 5

Expand All @@ -246,10 +242,7 @@
"version": 1,
"disable_existing_loggers": False,
"formatters": {
"verbose": {
"format": "%(levelname)s %(asctime)s %(module)s "
"%(process)d %(thread)d %(message)s"
}
"verbose": {"format": "%(levelname)s %(asctime)s %(module)s " "%(process)d %(thread)d %(message)s"}
},
"handlers": {
"console": {
Expand Down Expand Up @@ -316,12 +309,7 @@
SCRAM_DENIED_GROUPS = ["svc_scram_denied"]

# This is the set of all the groups
SCRAM_GROUPS = (
SCRAM_ADMIN_GROUPS
+ SCRAM_READWRITE_GROUPS
+ SCRAM_READONLY_GROUPS
+ SCRAM_DENIED_GROUPS
)
SCRAM_GROUPS = SCRAM_ADMIN_GROUPS + SCRAM_READWRITE_GROUPS + SCRAM_READONLY_GROUPS + SCRAM_DENIED_GROUPS

# This is the full set of groups

Expand Down
4 changes: 1 addition & 3 deletions config/settings/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,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")

# WhiteNoise
# ------------------------------------------------------------------------------
Expand Down
19 changes: 5 additions & 14 deletions config/settings/production.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
DATABASES["default"]["ATOMIC_REQUESTS"] = True # noqa F405
DATABASES["default"]["CONN_MAX_AGE"] = env.int("CONN_MAX_AGE", default=60) # noqa F405
if env("POSTGRES_SSL"):
DATABASES["default"]["OPTIONS"] = {'sslmode': 'require'} # noqa F405
DATABASES["default"]["OPTIONS"] = {"sslmode": "require"} # noqa F405

# CACHES
# ------------------------------------------------------------------------------
Expand Down Expand Up @@ -48,15 +48,11 @@
# 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
SECURE_CONTENT_TYPE_NOSNIFF = env.bool(
"DJANGO_SECURE_CONTENT_TYPE_NOSNIFF", default=True
)
SECURE_CONTENT_TYPE_NOSNIFF = env.bool("DJANGO_SECURE_CONTENT_TYPE_NOSNIFF", default=True)

# STATIC
# ------------------------
Expand Down Expand Up @@ -114,10 +110,7 @@
"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"
}
"verbose": {"format": "%(levelname)s %(asctime)s %(module)s " "%(process)d %(thread)d %(message)s"}
},
"handlers": {
"mail_admins": {
Expand Down Expand Up @@ -152,9 +145,7 @@
MIDDLEWARE += ["mozilla_django_oidc.middleware.SessionRefresh"] # noqa F405

# Extend middleware to add OIDC auth backend
AUTHENTICATION_BACKENDS += [
"scram.route_manager.authentication_backends.ESnetAuthBackend"
] # noqa F405
AUTHENTICATION_BACKENDS += ["scram.route_manager.authentication_backends.ESnetAuthBackend"] # noqa F405

# https://docs.djangoproject.com/en/dev/ref/settings/#login-url
LOGIN_URL = "oidc_authentication_init"
Expand Down
4 changes: 1 addition & 3 deletions merge_production_dotenvs_in_dotenv.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@
DOTENV_FILE_PATH = ROOT_DIR_PATH / ".env"


def merge(
output_file_path: str, merged_file_paths: Sequence[str], append_linesep: bool = True
) -> None:
def merge(output_file_path: str, merged_file_paths: Sequence[str], append_linesep: bool = True) -> None:
with open(output_file_path, "w") as output_file:
for merged_file_path in merged_file_paths:
with open(merged_file_path, "r") as merged_file:
Expand Down
7 changes: 1 addition & 6 deletions scram/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,2 @@
__version__ = "0.1.0"
__version_info__ = tuple(
[
int(num) if num.isdigit() else num
for num in __version__.replace("-", ".", 1).split(".")
]
)
__version_info__ = tuple([int(num) if num.isdigit() else num for num in __version__.replace("-", ".", 1).split(".")])
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ def update_site_forward(apps, schema_editor):
def update_site_backward(apps, schema_editor):
"""Revert site domain and name to default."""
Site = apps.get_model("sites", "Site")
Site.objects.update_or_create(
id=settings.SITE_ID, defaults={"domain": "example.com", "name": "example.com"}
)
Site.objects.update_or_create(id=settings.SITE_ID, defaults={"domain": "example.com", "name": "example.com"})


class Migration(migrations.Migration):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
class Migration(migrations.Migration):

dependencies = [
('sites', '0003_set_site_domain_and_name'),
("sites", "0003_set_site_domain_and_name"),
]

operations = [
migrations.AlterModelOptions(
name='site',
options={'ordering': ['domain'], 'verbose_name': 'site', 'verbose_name_plural': 'sites'},
name="site",
options={"ordering": ["domain"], "verbose_name": "site", "verbose_name_plural": "sites"},
),
]
4 changes: 1 addition & 3 deletions scram/route_manager/api/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ class PrefixTooLarge(APIException):

class IgnoredRoute(APIException):
status_code = 400
default_detail = (
"This CIDR is on the ignore list. You are not allowed to add it here."
)
default_detail = "This CIDR is on the ignore list. You are not allowed to add it here."
default_code = "ignored_route"


Expand Down
4 changes: 1 addition & 3 deletions scram/route_manager/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,7 @@ def create(self, validated_data):

route_instance, created = Route.objects.get_or_create(route=valid_route)
actiontype_instance = ActionType.objects.get(name=actiontype)
entry_instance, created = Entry.objects.get_or_create(
route=route_instance, actiontype=actiontype_instance
)
entry_instance, created = Entry.objects.get_or_create(route=route_instance, actiontype=actiontype_instance)

logger.debug(f"{comment}")
update_change_reason(entry_instance, comment)
Expand Down
27 changes: 7 additions & 20 deletions scram/route_manager/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,7 @@

from ..models import ActionType, Client, Entry, IgnoreEntry
from .exceptions import ActiontypeNotAllowed, IgnoredRoute, PrefixTooLarge
from .serializers import (
ActionTypeSerializer,
ClientSerializer,
EntrySerializer,
IgnoreEntrySerializer,
)
from .serializers import ActionTypeSerializer, ClientSerializer, EntrySerializer, IgnoreEntrySerializer

channel_layer = get_channel_layer()

Expand Down Expand Up @@ -86,19 +81,13 @@ def perform_create(self, serializer):
# Make sure this client is authorized to add this entry with this actiontype
if self.request.data.get("uuid"):
client_uuid = self.request.data["uuid"]
authorized_actiontypes = Client.objects.filter(
uuid=client_uuid
).values_list("authorized_actiontypes__name", flat=True)
authorized_client = Client.objects.filter(uuid=client_uuid).values(
"is_authorized"
authorized_actiontypes = Client.objects.filter(uuid=client_uuid).values_list(
"authorized_actiontypes__name", flat=True
)
authorized_client = Client.objects.filter(uuid=client_uuid).values("is_authorized")
if not authorized_client or actiontype not in authorized_actiontypes:
logging.debug(
f"Client {client_uuid} actiontypes: {authorized_actiontypes}"
)
logging.info(
f"{client_uuid} is not allowed to add an entry to the {actiontype} list"
)
logging.debug(f"Client {client_uuid} actiontypes: {authorized_actiontypes}")
logging.info(f"{client_uuid} is not allowed to add an entry to the {actiontype} list")
raise ActiontypeNotAllowed()
elif not self.request.user.has_perm("route_manager.can_add_entry"):
raise PermissionDenied()
Expand All @@ -109,9 +98,7 @@ def perform_create(self, serializer):
ignore_entries = []
for ignore_entry in overlapping_ignore.values():
ignore_entries.append(str(ignore_entry["route"]))
logging.info(
f"Cannot proceed adding {route}. The ignore list contains {ignore_entries}"
)
logging.info(f"Cannot proceed adding {route}. The ignore list contains {ignore_entries}")
raise IgnoredRoute
else:
# Must match a channel name defined in asgi.py
Expand Down
9 changes: 4 additions & 5 deletions scram/route_manager/migrations/0001_initial.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,14 @@ class Migration(migrations.Migration):

initial = True

dependencies = [
]
dependencies = []

operations = [
migrations.CreateModel(
name='IPAddress',
name="IPAddress",
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('ip', netfields.fields.InetAddressField(max_length=39)),
("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
("ip", netfields.fields.InetAddressField(max_length=39)),
],
),
]
6 changes: 3 additions & 3 deletions scram/route_manager/migrations/0002_ipaddress_uuid.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@
class Migration(migrations.Migration):

dependencies = [
('route_manager', '0001_initial'),
("route_manager", "0001_initial"),
]

operations = [
migrations.AddField(
model_name='ipaddress',
name='uuid',
model_name="ipaddress",
name="uuid",
field=models.UUIDField(db_index=True, default=uuid.uuid4, editable=False),
),
]
12 changes: 6 additions & 6 deletions scram/route_manager/migrations/0003_auto_20210408_0413.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,19 @@
class Migration(migrations.Migration):

dependencies = [
('route_manager', '0002_ipaddress_uuid'),
("route_manager", "0002_ipaddress_uuid"),
]

operations = [
migrations.CreateModel(
name='Route',
name="Route",
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('route', netfields.fields.InetAddressField(max_length=39, unique=True)),
('uuid', models.UUIDField(db_index=True, default=uuid.uuid4, editable=False)),
("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
("route", netfields.fields.InetAddressField(max_length=39, unique=True)),
("uuid", models.UUIDField(db_index=True, default=uuid.uuid4, editable=False)),
],
),
migrations.DeleteModel(
name='IPAddress',
name="IPAddress",
),
]
13 changes: 8 additions & 5 deletions scram/route_manager/migrations/0004_actiontype.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,19 @@
class Migration(migrations.Migration):

dependencies = [
('route_manager', '0003_auto_20210408_0413'),
("route_manager", "0003_auto_20210408_0413"),
]

operations = [
migrations.CreateModel(
name='ActionType',
name="ActionType",
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=30, verbose_name='One-word description of the action')),
('available', models.BooleanField(default=True, verbose_name='Is this a valid choice for new entries?')),
("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
("name", models.CharField(max_length=30, verbose_name="One-word description of the action")),
(
"available",
models.BooleanField(default=True, verbose_name="Is this a valid choice for new entries?"),
),
],
),
]
Loading