Skip to content

Commit

Permalink
Merge pull request #64 from rockychen-dpaw/master
Browse files Browse the repository at this point in the history
Migrate auth2 from oim01 and oim02 to az-aks-prod01
  • Loading branch information
rockychen-dpaw authored Jun 24, 2024
2 parents e764bcb + 9435c85 commit ffad1f2
Show file tree
Hide file tree
Showing 56 changed files with 4,042 additions and 1,925 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
.env*
env*
*-dev.*
*_dev
.coverage
media/
logs/
Expand Down
24 changes: 17 additions & 7 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Prepare the base environment.
FROM python:3.10.12-slim-buster as builder_base_authome
FROM python:3.12.3-slim-bookworm as builder_base_authome
MAINTAINER [email protected]
LABEL org.opencontainers.image.source https://github.com/dbca-wa/authome
RUN apt-get update -y \
Expand All @@ -16,12 +16,20 @@ COPY poetry.lock pyproject.toml /app/
RUN poetry config virtualenvs.create false \
&& poetry install --only main --no-interaction --no-ansi

#update permissoins
RUN chmod 755 /etc
RUN chmod 555 /etc/bash.bashrc

#update add user
RUN addgroup -gid 1000 app
RUN adduser -uid 1000 --gid 1000 --no-create-home --disabled-login app

# Install Python libs from pyproject.toml.
FROM builder_base_authome as python_libs_authome
WORKDIR /app/release
# Install the project.
FROM python_libs_authome
COPY manage.py gunicorn.py testperformance testrequestheaders ./
COPY manage.py gunicorn.py testperformance testrequestheaders testrediscluster testperformance pyproject.toml ./
COPY authome ./authome
COPY templates ./templates
RUN export IGNORE_LOADING_ERROR=True ; python manage.py collectstatic --noinput --no-post-process
Expand All @@ -30,13 +38,13 @@ RUN cp -rf /app/release /app/dev

#comment out logger.debug to improve perfornace in production environment.
RUN find ./ -type f -iname '*.py' -exec sed -i 's/logger\.debug/#logger.debug/g' "{}" +;
RUN find ./ -type f -iname '*.py' -exec sed -i 's/from \. import performance/#from . import performance/g' "{}" +;
RUN find ./ -type f -iname '*.py' -exec sed -i 's/from \.\. import performance/#from .. import performance/g' "{}" +;
RUN find ./ -type f -iname '*.py' -exec sed -E -i 's/from\s+\.\s+import\s+performance/#from . import performance/g' "{}" +;
RUN find ./ -type f -iname '*.py' -exec sed -E -i 's/from\s+\.\.\s+import\s+performance/#from .. import performance/g' "{}" +;
RUN find ./ -type f -iname '*.py' -exec sed -i 's/performance\.start_processingstep/#performance.start_processingstep/g' "{}" +;
RUN find ./ -type f -iname '*.py' -exec sed -i 's/performance\.end_processingstep/#performance.end_processingstep/g' "{}" +;

RUN find ./ -type f -iname '*.py' -exec sed -i 's/from \.models import DebugLog/#from .models import DebugLog/g' "{}" +;
RUN find ./ -type f -iname '*.py' -exec sed -i 's/from \.\.models import DebugLog/#from ..models import DebugLog/g' "{}" +;
RUN find ./ -type f -iname '*.py' -exec sed -E -i 's/from\s+\.models\s+import\s+DebugLog/#from .models import DebugLog/g' "{}" +;
RUN find ./ -type f -iname '*.py' -exec sed -E -i 's/from\s+\.\.models\s+import\s+DebugLog/#from ..models import DebugLog/g' "{}" +;
RUN find ./ -type f -iname '*.py' -exec sed -i 's/DebugLog\.log/#DebugLog.log/g' "{}" +;
RUN find ./ -type f -iname '*.py' -exec sed -i 's/DebugLog\.attach_request/#DebugLog.attach_request/g' "{}" +;

Expand Down Expand Up @@ -65,7 +73,9 @@ fi \n\

RUN chmod 555 run_command

RUN chown -R app:app /app

# Run the application as the www-data user.
USER www-data
USER app
EXPOSE 8080
CMD ./start_app
8 changes: 0 additions & 8 deletions authome/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +0,0 @@
from django.apps import AppConfig

class AuthomeConfig(AppConfig):
name = "authome"
verbose_name = "AUTHENTICATION AND AUTHORIZATION"

default_app_config = 'authome.AuthomeConfig'

80 changes: 43 additions & 37 deletions authome/admin/adminsite.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from django.contrib import auth
from django.urls import resolve

from .. import models
from .. import models as auth2_models
from .. import utils
from .. import signals

Expand All @@ -20,7 +20,7 @@ def admin_view(self, view, cacheable=False):
def _view(request, *args, **kwargs):
utils.attach_request(request)
try:
if models.can_access(request.user.email,settings.AUTH2_DOMAIN,'/admin/authome/tools/'):
if auth2_models.can_access(request.user.email,settings.AUTH2_DOMAIN,'/admin/authome/tools/'):
url_name = resolve(request.path_info).url_name
if url_name in ("index","app_list"):
signals.global_warning.send(sender=object,request=request)
Expand All @@ -39,13 +39,15 @@ def _build_app_dict(self, request, label=None):
app_dict = {}

if label:
registered_models = {
m: m_a for m, m_a in self._registry.items()
models = {
m: m_a
for m, m_a in self._registry.items()
if m._meta.app_label == label
}
else:
registered_models = self._registry
for model, model_admin in registered_models.items():
models = self._registry

for model, model_admin in models.items():

app_label = model._meta.app_label

Expand All @@ -62,44 +64,49 @@ def _build_app_dict(self, request, label=None):

info = (app_label, model._meta.model_name)
model_dict = {
'name': capfirst(model._meta.verbose_name_plural),
'object_name': model._meta.object_name,
'perms': perms,
'admin_url': None,
'add_url': None,
"model": model,
"name": capfirst(model._meta.verbose_name_plural),
"object_name": model._meta.object_name,
"perms": perms,
"admin_url": None,
"add_url": None,
}
if perms.get('change') or perms.get('view'):
model_dict['view_only'] = not perms.get('change')
if perms.get("change") or perms.get("view"):
model_dict["view_only"] = not perms.get("change")
try:
model_dict['admin_url'] = reverse('admin:%s_%s_changelist' % info, current_app=self.name)
model_dict["admin_url"] = reverse(
"admin:%s_%s_changelist" % info, current_app=self.name
)
except NoReverseMatch:
pass
if perms.get('add'):
if perms.get("add"):
try:
model_dict['add_url'] = reverse('admin:%s_%s_add' % info, current_app=self.name)
model_dict["add_url"] = reverse(
"admin:%s_%s_add" % info, current_app=self.name
)
except NoReverseMatch:
pass

if not model_dict.get('admin_url') or not models.can_access(request.user.email,settings.AUTH2_DOMAIN,model_dict['admin_url']):
if not model_dict.get('admin_url') or not auth2_models.can_access(request.user.email,settings.AUTH2_DOMAIN,model_dict['admin_url']):
continue

if app_label in app_dict:
app_dict[app_label]['models'].append(model_dict)
else:
app_dict[app_label] = {
'name': apps.get_app_config(app_label).verbose_name,
'app_label': app_label,
'app_url': reverse(
'admin:app_list',
kwargs={'app_label': app_label},
"name": apps.get_app_config(app_label).verbose_name,
"app_label": app_label,
"app_url": reverse(
"admin:app_list",
kwargs={"app_label": app_label},
current_app=self.name,
),
'has_module_perms': has_module_perms,
'models': [model_dict],
"has_module_perms": has_module_perms,
"models": [model_dict],
}
#add others app
if models.can_access(request.user.email,settings.AUTH2_DOMAIN,'/admin/authome/tools/'):
app_label = models.UserGroup._meta.app_label
if auth2_models.can_access(request.user.email,settings.AUTH2_DOMAIN,'/admin/authome/tools/'):
app_label = auth2_models.UserGroup._meta.app_label
if app_label in app_dict:
app_dict[app_label]["models"].append({
'name': "Renew Apple Secret Key",
Expand All @@ -110,11 +117,10 @@ def _build_app_dict(self, request, label=None):
})


if label:
return app_dict.get(label)
return app_dict

admin_site = Auth2AdminSite()
#admin_site = djangoadmin.AdminSite()

#register all model admins which are already registered in django admin to auth2 admin site
registered_admins = [(model,model_admin)for model, model_admin in djangoadmin.site._registry.items()]
Expand All @@ -129,28 +135,28 @@ def _build_app_dict(self, request, label=None):

if settings.AUTH2_CLUSTER_ENABLED:
from .clusteradmin import Auth2ClusterAdmin
admin_site.register(models.Auth2Cluster,Auth2ClusterAdmin)
admin_site.register(auth2_models.Auth2Cluster,Auth2ClusterAdmin)
from .clusteradmin import (UserGroupAdmin,IdentityProviderAdmin,CustomizableUserflowAdmin,UserGroupAuthorizationAdmin,UserAdmin,UserAccessTokenAdmin,SystemUserAccessTokenAdmin)
from .admin import (SystemUserAdmin,UserTOTPAdmin)
else:
from .admin import (UserAdmin,SystemUserAdmin,UserGroupAuthorizationAdmin,UserGroupAdmin,UserAccessTokenAdmin,SystemUserAccessTokenAdmin,
IdentityProviderAdmin,CustomizableUserflowAdmin,UserTOTPAdmin)

from .debugadmin import DebugLogAdmin
admin_site.register(models.DebugLog,DebugLogAdmin)
admin_site.register(auth2_models.DebugLog,DebugLogAdmin)

if settings.TRAFFIC_MONITOR_LEVEL > 0:
from .monitoradmin import TrafficReportAdmin,TrafficDataAdmin
admin_site.register(models.TrafficData,TrafficDataAdmin)
admin_site.register(models.TrafficReport,TrafficReportAdmin)
admin_site.register(auth2_models.TrafficData,TrafficDataAdmin)
admin_site.register(auth2_models.TrafficReport,TrafficReportAdmin)


admin_site.register(NormalUser,UserAdmin)
admin_site.register(SystemUser,SystemUserAdmin)
admin_site.register(models.UserGroupAuthorization,UserGroupAuthorizationAdmin)
admin_site.register(models.UserGroup,UserGroupAdmin)
admin_site.register(auth2_models.UserGroupAuthorization,UserGroupAuthorizationAdmin)
admin_site.register(auth2_models.UserGroup,UserGroupAdmin)
admin_site.register(SystemUserToken,SystemUserAccessTokenAdmin)
admin_site.register(NormalUserToken,UserAccessTokenAdmin)
admin_site.register(models.IdentityProvider,IdentityProviderAdmin)
admin_site.register(models.CustomizableUserflow,CustomizableUserflowAdmin)
admin_site.register(models.UserTOTP,UserTOTPAdmin)
admin_site.register(auth2_models.IdentityProvider,IdentityProviderAdmin)
admin_site.register(auth2_models.CustomizableUserflow,CustomizableUserflowAdmin)
admin_site.register(auth2_models.UserTOTP,UserTOTPAdmin)
4 changes: 2 additions & 2 deletions authome/admin/clusteradmin.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from ..cache import cache,get_defaultcache
from . import admin
from .. import utils
from ..views.monitorviews import _get_localhealthcheck,_clusterstatus
from ..views.monitorviews import _check_localhealth,_clusterstatus

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -207,7 +207,7 @@ def _get_cache_status(self,obj,key,f_name=None,default="N/A"):
return f_name(obj.cache_status.get(key,default)) if f_name else obj.cache_status.get(key,default)
except AttributeError as ex:
if obj.clusterid == settings.AUTH2_CLUSTERID:
healthcheck = _get_localhealthcheck()
healthcheck = _check_localhealth()
data = {}
for cls in (models.UserGroup,models.UserGroupAuthorization,models.CustomizableUserflow,models.IdentityProvider):
cls.refresh_cache_if_required()
Expand Down
2 changes: 1 addition & 1 deletion authome/admin/monitoradmin.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ def _subreports(self,obj):
if obj.cluster is None:
if obj.clusterid is None:
#non cluser env
return mark_safe("<A href='{}?clusterid__isnull=Truestart_time__gte={}&end_time__lte={}'>Details</A>".format(reverse(self.traffic_data_list_url_name),self._start_time(obj),self._end_time(obj)))
return mark_safe("<A href='{}?clusterid__isnull=True&start_time__gte={}&end_time__lte={}'>Details</A>".format(reverse(self.traffic_data_list_url_name),self._start_time(obj),self._end_time(obj)))
else:
#overall report
if obj.report_type == models.TrafficReport.DAILY_REPORT:
Expand Down
8 changes: 8 additions & 0 deletions authome/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from django.apps import AppConfig

class AuthomeConfig(AppConfig):
name = "authome"
verbose_name = "AUTHENTICATION AND AUTHORIZATION"
default = True


16 changes: 10 additions & 6 deletions authome/backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

from .models import IdentityProvider, CustomizableUserflow
from . import utils
from .exceptions import AzureADB2CAuthenticateFailed
from .exceptions import AzureADB2CAuthenticateFailed,PolicyNotConfiguredException

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -41,8 +41,12 @@ def policy(self):
#if request has a property policy, use that policy directly,
#The features(mfa set, mfa reset, and password reset) use this proerty 'policy' to specific the customized policy
policy = request.policy
if not policy:
raise PolicyNotConfiguredException('ADB2C policy is not configured for request({})'.format(request.path))
elif not policy.lower().startswith('b2c_'):
raise PolicyNotConfiguredException('The name of ADB2C policy({}) should be started with "b2c_" case-insensitive.'.format(policy))
else:
domain = (utils.get_domain(request.session.get(utils.REDIRECT_FIELD_NAME)) or utils.get_host(request)) if request else None
domain = (utils.get_domain(request.session.get(utils.REDIRECT_FIELD_NAME)) or request.get_host()) if request else None
if not domain or domain == settings.AUTH2_DOMAIN:
#Domain is None or dmain is auth2, use the user flow's default policy
userflow = CustomizableUserflow.get_userflow(None)
Expand All @@ -66,10 +70,10 @@ def policy(self):
policy = userflow.default

logger.debug("Prefered idp is '{}', Choosed userflow is '{}', request domain is '{}' ".format(idp,policy,domain))

if not policy or not policy.lower().startswith('b2c_'):
raise AuthException('SOCIAL_AUTH_AZUREAD_B2C_OAUTH2_POLICY is '
'required and should start with `b2c_`')
if not policy:
raise PolicyNotConfiguredException('ADB2C policy is not configured for domain({})'.format(domain))
elif not policy.lower().startswith('b2c_'):
raise PolicyNotConfiguredException('The name of ADB2C policy({}) should be started with "b2c_" case-insensitive.'.format(policy))

return policy

Expand Down
24 changes: 18 additions & 6 deletions authome/basetest.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,24 @@
import base64

from .models import UserGroup,UserGroupAuthorization,UserAuthorization,can_access,UserToken,User,CustomizableUserflow
from .cache import cache
from .cache import cache,get_usercache
from authome import patch
groupid = 0

class Auth2Client(Client):
def get(self,*args,**kwargs):
kwargs["HTTP_HOST"] = settings.AUTH2_DOMAIN
kwargs["HTTP_SERVER_NAME"] = settings.AUTH2_DOMAIN

return super().get(*args,**kwargs)
def get(self,path, authorization=None,domain=None,url=None):
headers={"HOST":settings.AUTH2_DOMAIN,"SERVER_NAME":settings.AUTH2_DOMAIN}
if authorization:
headers["AUTHORIZATION"] = authorization
if domain:
headers["X_UPSTREAM_SERVER_NAME"] = domain
elif path in ("/sso/auth","/sso/auth_basic","/sso/auth_optional"):
headers["X_UPSTREAM_SERVER_NAME"] = settings.AUTH2_DOMAIN

if url:
headers["X_UPSTREAM_REQUEST_URI"] = url

return super().get(path,headers=headers)

class BaseAuthTestCase(TestCase):
client_class = Auth2Client
Expand Down Expand Up @@ -105,6 +113,10 @@ def populate_testdata(self):
token = UserToken(user=obj,enabled=True)
token.generate_token()
token.save()
usercache = get_usercache(token.user_id)
if usercache and usercache.get(settings.GET_USERTOKEN_KEY(token.user_id)):
#Only cache the user token only if it is already cached
usercache.set(settings.GET_USERTOKEN_KEY(token.user_id),token,settings.STAFF_CACHE_TIMEOUT if token.user.is_staff else settings.USER_CACHE_TIMEOUT)
self.test_users = users

if self.test_usergroupauthorization:
Expand Down
Loading

0 comments on commit ffad1f2

Please sign in to comment.