Skip to content

Commit

Permalink
oidc keycloak adaptions
Browse files Browse the repository at this point in the history
  • Loading branch information
lme-nca committed Apr 11, 2024
1 parent 1dfcc3f commit 77a171f
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 11 deletions.
3 changes: 3 additions & 0 deletions dojo/context_processors.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ def globalize_vars(request):
"AZUREAD_TENANT_OAUTH2_GET_GROUPS": settings.AZUREAD_TENANT_OAUTH2_GET_GROUPS,
"AZUREAD_TENANT_OAUTH2_GROUPS_FILTER": settings.AZUREAD_TENANT_OAUTH2_GROUPS_FILTER,
"AZUREAD_TENANT_OAUTH2_CLEANUP_GROUPS": settings.AZUREAD_TENANT_OAUTH2_CLEANUP_GROUPS,
"KEYCLOAK_TENANT_OAUTH2_GET_GROUPS": settings.AZUREAD_TENANT_OAUTH2_GET_GROUPS,
"KEYCLOAK_TENANT_OAUTH2_GROUPS_FILTER": settings.AZUREAD_TENANT_OAUTH2_GROUPS_FILTER,
"KEYCLOAK_TENANT_OAUTH2_CLEANUP_GROUPS": settings.AZUREAD_TENANT_OAUTH2_CLEANUP_GROUPS,
"KEYCLOAK_ENABLED": settings.KEYCLOAK_OAUTH2_ENABLED,
"SOCIAL_AUTH_KEYCLOAK_LOGIN_BUTTON_TEXT": settings.SOCIAL_AUTH_KEYCLOAK_LOGIN_BUTTON_TEXT,
"GITHUB_ENTERPRISE_ENABLED": settings.GITHUB_ENTERPRISE_OAUTH2_ENABLED,
Expand Down
18 changes: 18 additions & 0 deletions dojo/db_migrations/0209_alter_dojo_group_social_provider.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 4.1.13 on 2024-04-11 12:16

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('dojo', '0208_merge_acunetix'),
]

operations = [
migrations.AlterField(
model_name='dojo_group',
name='social_provider',
field=models.CharField(blank=True, choices=[('AzureAD', 'AzureAD'), ('Remote', 'Remote'), ('Keycloak', 'Keycloak')], help_text='Group imported from a social provider.', max_length=10, null=True, verbose_name='Social Authentication Provider'),
),
]
5 changes: 2 additions & 3 deletions dojo/group/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
from django.contrib.auth.models import Group
from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver
from dojo.models import Dojo_Group, Dojo_Group_Member, Role
from django.conf import settings
from dojo.models import Dojo_Group, Dojo_Group_Member, Role, Dojo_User


def get_auth_group_name(group, attempt=0):
Expand Down Expand Up @@ -41,7 +40,7 @@ def group_post_save_handler(sender, **kwargs):
group.save()

user = get_current_user()
if user and not settings.AZUREAD_TENANT_OAUTH2_GET_GROUPS:
if user and isinstance(user, Dojo_User):
# Add the current user as the owner of the group
member = Dojo_Group_Member()
member.user = user
Expand Down
2 changes: 2 additions & 0 deletions dojo/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,9 +250,11 @@ class UserContactInfo(models.Model):
class Dojo_Group(models.Model):
AZURE = 'AzureAD'
REMOTE = 'Remote'
KEYCLOAK = 'Keycloak'
SOCIAL_CHOICES = (
(AZURE, _('AzureAD')),
(REMOTE, _('Remote')),
(KEYCLOAK, _('Keycloak')),
)
name = models.CharField(max_length=255, unique=True)
description = models.CharField(max_length=4000, null=True, blank=True)
Expand Down
20 changes: 20 additions & 0 deletions dojo/pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from django.conf import settings
from dojo.models import Product, Product_Member, Product_Type, Role, Dojo_Group, Dojo_Group_Member
from social_core.backends.azuread_tenant import AzureADTenantOAuth2
from social_core.backends.open_id_connect import OpenIdConnectAuth
from social_core.backends.google import GoogleOAuth2
from dojo.authorization.roles_permissions import Permissions, Roles
from dojo.product.queries import get_authorized_products
Expand Down Expand Up @@ -65,6 +66,25 @@ def modify_permissions(backend, uid, user=None, social=None, *args, **kwargs):
pass


def update_keycloak_groups(backend, uid, user=None, social=None, *args, **kwargs):
if settings.KEYCLOAK_OAUTH2_ENABLED and settings.KEYCLOAK_TENANT_OAUTH2_GET_GROUPS and isinstance(backend, OpenIdConnectAuth):
group_names = []
if 'groups' not in kwargs['response'] or kwargs['response']['groups'] == "":
logger.warning("No groups in response. Stopping to update groups of user based on azureAD")
return
group_ids = kwargs['response']['groups']
for group_from_response in group_ids:
if settings.KEYCLOAK_TENANT_OAUTH2_GROUPS_FILTER == "" or re.search(settings.KEYCLOAK_TENANT_OAUTH2_GROUPS_FILTER, group_from_response):
group_names.append(group_from_response)
else:
logger.debug("Skipping group " + group_from_response + " due to KEYCLOAK_TENANT_OAUTH2_GROUPS_FILTER " + settings.KEYCLOAK_TENANT_OAUTH2_GROUPS_FILTER)

if len(group_names) > 0:
assign_user_to_groups(user, group_names, 'Keycloak')
if settings.KEYCLOAK_TENANT_OAUTH2_CLEANUP_GROUPS:
cleanup_old_groups_for_user(user, group_names)


def update_azure_groups(backend, uid, user=None, social=None, *args, **kwargs):
if settings.AZUREAD_TENANT_OAUTH2_ENABLED and settings.AZUREAD_TENANT_OAUTH2_GET_GROUPS and isinstance(backend, AzureADTenantOAuth2):
# In some wild cases, there could be two social auth users
Expand Down
25 changes: 19 additions & 6 deletions dojo/settings/settings.dist.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@
DD_SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_GET_GROUPS=(bool, False),
DD_SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_GROUPS_FILTER=(str, ''),
DD_SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_CLEANUP_GROUPS=(bool, True),
DD_SOCIAL_AUTH_KEYCLOAK_OAUTH2_GET_GROUPS=(bool, False),
DD_SOCIAL_AUTH_KEYCLOAK_OAUTH2_CLEANUP_GROUPS=(bool, True),
DD_SOCIAL_AUTH_KEYCLOAK_OAUTH2_GROUPS_FILTER=(str, ''),
DD_SOCIAL_AUTH_GITLAB_OAUTH2_ENABLED=(bool, False),
DD_SOCIAL_AUTH_GITLAB_PROJECT_AUTO_IMPORT=(bool, False),
DD_SOCIAL_AUTH_GITLAB_PROJECT_IMPORT_TAGS=(bool, False),
Expand All @@ -134,6 +137,7 @@
DD_SOCIAL_AUTH_GITLAB_API_URL=(str, 'https://gitlab.com'),
DD_SOCIAL_AUTH_GITLAB_SCOPE=(list, ['read_user', 'openid']),
DD_SOCIAL_AUTH_KEYCLOAK_OAUTH2_ENABLED=(bool, False),
DD_SOCIAL_AUTH_OIDC_OIDC_ENDPOINT=(str, ''),
DD_SOCIAL_AUTH_KEYCLOAK_KEY=(str, ''),
DD_SOCIAL_AUTH_KEYCLOAK_SECRET=(str, ''),
DD_SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY=(str, ''),
Expand Down Expand Up @@ -533,7 +537,8 @@ def generate_url(scheme, double_slashes, user, password, host, port, path, param
'dojo.okta.OktaOAuth2',
'social_core.backends.azuread_tenant.AzureADTenantOAuth2',
'social_core.backends.gitlab.GitLabOAuth2',
'social_core.backends.keycloak.KeycloakOAuth2',
# 'social_core.backends.keycloak.KeycloakOAuth2',
'social_core.backends.open_id_connect.OpenIdConnectAuth',
'social_core.backends.github_enterprise.GithubEnterpriseOAuth2',
'dojo.remote_user.RemoteUserBackend',
'django.contrib.auth.backends.RemoteUserBackend',
Expand Down Expand Up @@ -569,6 +574,7 @@ def generate_url(scheme, double_slashes, user, password, host, port, path, param
'social_core.pipeline.social_auth.load_extra_data',
'social_core.pipeline.user.user_details',
'dojo.pipeline.update_azure_groups',
'dojo.pipeline.update_keycloak_groups',
'dojo.pipeline.update_product_access',
)

Expand Down Expand Up @@ -630,13 +636,20 @@ def generate_url(scheme, double_slashes, user, password, host, port, path, param
SOCIAL_AUTH_TRAILING_SLASH = env('DD_SOCIAL_AUTH_TRAILING_SLASH')

KEYCLOAK_OAUTH2_ENABLED = env('DD_SOCIAL_AUTH_KEYCLOAK_OAUTH2_ENABLED')
SOCIAL_AUTH_KEYCLOAK_KEY = env('DD_SOCIAL_AUTH_KEYCLOAK_KEY')
SOCIAL_AUTH_KEYCLOAK_SECRET = env('DD_SOCIAL_AUTH_KEYCLOAK_SECRET')
SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY = env('DD_SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY')
SOCIAL_AUTH_KEYCLOAK_AUTHORIZATION_URL = env('DD_SOCIAL_AUTH_KEYCLOAK_AUTHORIZATION_URL')
SOCIAL_AUTH_KEYCLOAK_ACCESS_TOKEN_URL = env('DD_SOCIAL_AUTH_KEYCLOAK_ACCESS_TOKEN_URL')
SOCIAL_AUTH_OIDC_OIDC_ENDPOINT = env('DD_SOCIAL_AUTH_OIDC_OIDC_ENDPOINT')
SOCIAL_AUTH_OIDC_KEY = env('DD_SOCIAL_AUTH_KEYCLOAK_KEY')
SOCIAL_AUTH_OIDC_SECRET = env('DD_SOCIAL_AUTH_KEYCLOAK_SECRET')
SOCIAL_AUTH_KEYCLOAK_LOGIN_BUTTON_TEXT = env('DD_SOCIAL_AUTH_KEYCLOAK_LOGIN_BUTTON_TEXT')

KEYCLOAK_TENANT_OAUTH2_GET_GROUPS = env('DD_SOCIAL_AUTH_KEYCLOAK_OAUTH2_GET_GROUPS')
KEYCLOAK_TENANT_OAUTH2_CLEANUP_GROUPS = env('DD_SOCIAL_AUTH_KEYCLOAK_OAUTH2_CLEANUP_GROUPS')
KEYCLOAK_TENANT_OAUTH2_GROUPS_FILTER = env('DD_SOCIAL_AUTH_KEYCLOAK_OAUTH2_GROUPS_FILTER')

# SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY = env('DD_SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY')
# SOCIAL_AUTH_KEYCLOAK_AUTHORIZATION_URL = env('DD_SOCIAL_AUTH_KEYCLOAK_AUTHORIZATION_URL')
# SOCIAL_AUTH_KEYCLOAK_ACCESS_TOKEN_URL = env('DD_SOCIAL_AUTH_KEYCLOAK_ACCESS_TOKEN_URL')


GITHUB_ENTERPRISE_OAUTH2_ENABLED = env('DD_SOCIAL_AUTH_GITHUB_ENTERPRISE_OAUTH2_ENABLED')
SOCIAL_AUTH_GITHUB_ENTERPRISE_URL = env('DD_SOCIAL_AUTH_GITHUB_ENTERPRISE_URL')
SOCIAL_AUTH_GITHUB_ENTERPRISE_API_URL = env('DD_SOCIAL_AUTH_GITHUB_ENTERPRISE_API_URL')
Expand Down
2 changes: 1 addition & 1 deletion dojo/templates/dojo/login.html
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ <h3>{% trans "Login" %}</h3>
{% if KEYCLOAK_ENABLED is True %}
<div class="col-sm-offset-1 col-sm-2">
<button class="btn btn-success" type="button">
<a href="{% url 'social:begin' 'keycloak' %}?next={{ request.GET.next }}" style="color: rgb(255,255,255)">{{ SOCIAL_AUTH_KEYCLOAK_LOGIN_BUTTON_TEXT }}</a>
<a href="{% url 'social:begin' 'oidc' %}?next={{ request.GET.next }}" style="color: rgb(255,255,255)">{{ SOCIAL_AUTH_KEYCLOAK_LOGIN_BUTTON_TEXT }}</a>
</button>
</div>
{% endif %}
Expand Down
2 changes: 1 addition & 1 deletion dojo/user/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ def login_view(request):
elif settings.GITLAB_OAUTH2_ENABLED:
social_auth = 'gitlab'
elif settings.KEYCLOAK_OAUTH2_ENABLED:
social_auth = 'keycloak'
social_auth = 'oidc'
elif settings.AUTH0_OAUTH2_ENABLED:
social_auth = 'auth0'
elif settings.GITHUB_ENTERPRISE_OAUTH2_ENABLED:
Expand Down

0 comments on commit 77a171f

Please sign in to comment.