diff options
-rw-r--r-- | config.env.sample | 19 | ||||
-rw-r--r-- | requirements.txt | 1 | ||||
-rw-r--r-- | src/account/views.py | 43 | ||||
-rw-r--r-- | src/dashboard/views.py | 6 | ||||
-rw-r--r-- | src/laas_dashboard/settings.py | 27 | ||||
-rw-r--r-- | src/laas_dashboard/urls.py | 3 | ||||
-rw-r--r-- | src/templates/akraino/dashboard/landing.html | 1 | ||||
-rw-r--r-- | src/templates/base/base.html | 43 | ||||
-rw-r--r-- | src/templates/base/dashboard/landing.html | 6 | ||||
-rw-r--r-- | src/templates/base/dashboard/login.html | 5 |
10 files changed, 141 insertions, 13 deletions
diff --git a/config.env.sample b/config.env.sample index fadf0ed..5b34217 100644 --- a/config.env.sample +++ b/config.env.sample @@ -22,6 +22,12 @@ DB_PASS=sample_pass DB_SERVICE=postgres DB_PORT=5432 +# tells the dashboard to expect host forwarding from proxy (if using LFID, needs to be True) +EXPECT_HOST_FORWARDING=False + +# string indicating what authorization to deploy with +AUTH_SETTING=choose_auth # LFID or OAUTH + # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY=http://www.miniwebtool.com/django-secret-key-generator/ @@ -35,6 +41,19 @@ JIRA_URL=sample_url JIRA_USER_NAME=sample_jira_user JIRA_USER_PASSWORD=sample_jira_pass +# LFID +OIDC_CLIENT_ID=sample_id +OIDC_CLIENT_SECRET=sample_secret + +OIDC_AUTHORIZATION_ENDPOINT=https://linuxfoundation-test.auth0.com/authorize +OIDC_TOKEN_ENDPOINT=https://linuxfoundation-test.auth0.com/oauth/token +OIDC_USER_ENDPOINT=https://linuxfoundation-test.auth0.com/userinfo + +CLAIMS_ENDPOINT=https://sso.linuxfoundation.org/claims/ + +OIDC_RP_SIGN_ALGO=RS256 +OIDC_OP_JWKS_ENDPOINT=https://sso.linuxfoundation.org/.well-known/jwks.json + # Rabbitmq RABBITMQ_DEFAULT_USER=opnfv RABBITMQ_DEFAULT_PASS=opnfvopnfv diff --git a/requirements.txt b/requirements.txt index 7e2fbd1..b34dd1e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -15,3 +15,4 @@ requests==2.22.0 django-fernet-fields==0.6 pyyaml==3.13 pytz==2018.5 +mozilla-django-oidc==1.2.3 diff --git a/src/account/views.py b/src/account/views.py index d11a199..08da918 100644 --- a/src/account/views.py +++ b/src/account/views.py @@ -28,6 +28,7 @@ from django.views.generic import RedirectView, TemplateView, UpdateView from django.shortcuts import render from jira import JIRA from rest_framework.authtoken.models import Token +from mozilla_django_oidc.auth import OIDCAuthenticationBackend from account.forms import AccountSettingsForm @@ -58,6 +59,48 @@ class AccountSettingsView(UpdateView): return context +class MyOIDCAB(OIDCAuthenticationBackend): + def filter_users_by_claims(self, claims): + """ + Checks to see if user exists and create user if not + + Linux foundation does not allow users to change their + username, so chose to match users based on their username. + If this changes we will need to match users based on some + other criterea. + """ + username = claims.get(os.environ['CLAIMS_ENDPOINT'] + 'username') + + if not username: + return HttpResponse('No username provided, contact support.') + + try: + # For literally no (good) reason user needs to be a queryset + user = User.objects.filter(username=username) + return user + except User.DoesNotExist: + return self.UserModel.objects.none() + + def create_user(self, claims): + """ This creates a user and user profile""" + user = super(MyOIDCAB, self).create_user(claims) + user.username = claims.get(os.environ['CLAIMS_ENDPOINT'] + 'username') + user.save() + + up = UserProfile() + up.user = user + up.email_addr = claims.get('email') + up.save() + return user + + def update_user(self, user, claims): + """ If their account has different email, change the email """ + up = UserProfile.objects.get(user=user) + up.email_addr = claims.get('email') + up.save() + return user + + class JiraLoginView(RedirectView): def get_redirect_url(self, *args, **kwargs): consumer = oauth.Consumer(settings.OAUTH_CONSUMER_KEY, settings.OAUTH_CONSUMER_SECRET) diff --git a/src/dashboard/views.py b/src/dashboard/views.py index f9a908c..7c85250 100644 --- a/src/dashboard/views.py +++ b/src/dashboard/views.py @@ -22,6 +22,8 @@ from booking.models import Booking from resource_inventory.models import Image, ResourceProfile, ResourceQuery from workflow.workflow_manager import ManagerTracker +import os + def lab_list_view(request): labs = Lab.objects.all() @@ -78,13 +80,15 @@ def landing_view(request): else: bookings = None + LFID = True if os.environ['AUTH_SETTING'] == 'LFID' else False return render( request, 'dashboard/landing.html', { 'manager': manager is not None, 'title': "Welcome to the Lab as a Service Dashboard", - 'bookings': bookings + 'bookings': bookings, + 'LFID': LFID } ) diff --git a/src/laas_dashboard/settings.py b/src/laas_dashboard/settings.py index 86778c1..a32b1c5 100644 --- a/src/laas_dashboard/settings.py +++ b/src/laas_dashboard/settings.py @@ -31,6 +31,7 @@ INSTALLED_APPS = [ 'analytics', 'django.contrib.admin', 'django.contrib.auth', + 'mozilla_django_oidc', # needs to be defined after auth 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', @@ -38,7 +39,7 @@ INSTALLED_APPS = [ 'django.contrib.humanize', 'bootstrap4', 'rest_framework', - 'rest_framework.authtoken' + 'rest_framework.authtoken', ] MIDDLEWARE = [ @@ -52,6 +53,30 @@ MIDDLEWARE = [ 'account.middleware.TimezoneMiddleware', ] +if os.environ['AUTH_SETTING'] == 'LFID': + AUTHENTICATION_BACKENDS = ['account.views.MyOIDCAB'] + + # OpenID Authentications + OIDC_RP_CLIENT_ID = os.environ['OIDC_CLIENT_ID'] + OIDC_RP_CLIENT_SECRET = os.environ['OIDC_CLIENT_SECRET'] + + OIDC_OP_AUTHORIZATION_ENDPOINT = os.environ['OIDC_AUTHORIZATION_ENDPOINT'] + OIDC_OP_TOKEN_ENDPOINT = os.environ['OIDC_TOKEN_ENDPOINT'] + OIDC_OP_USER_ENDPOINT = os.environ['OIDC_USER_ENDPOINT'] + + LOGIN_REDIRECT_URL = os.environ['DASHBOARD_URL'] + LOGOUT_REDIRECT_URL = os.environ['DASHBOARD_URL'] + + OIDC_RP_SIGN_ALGO = os.environ["OIDC_RP_SIGN_ALGO"] + + if OIDC_RP_SIGN_ALGO == "RS256": + OIDC_OP_JWKS_ENDPOINT = os.environ["OIDC_OP_JWKS_ENDPOINT"] + +# This is for LFID auth setups w/ an HTTPS proxy +if os.environ['EXPECT_HOST_FORWARDING'] == 'True': + SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', "https") + USE_X_FORWARDED_HOST = True + ROOT_URLCONF = 'laas_dashboard.urls' TEMPLATE_OVERRIDE = os.environ.get("TEMPLATE_OVERRIDE_DIR", "") # the user's custom template dir diff --git a/src/laas_dashboard/urls.py b/src/laas_dashboard/urls.py index 17cbe84..7a37d7e 100644 --- a/src/laas_dashboard/urls.py +++ b/src/laas_dashboard/urls.py @@ -41,7 +41,8 @@ urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')), url(r'^api/', include('api.urls')), - url(r'^messages/', include('notifier.urls', namespace='notifier')) + url(r'^messages/', include('notifier.urls', namespace='notifier')), + url(r'^oidc/', include('mozilla_django_oidc.urls')), ] if settings.DEBUG is True: diff --git a/src/templates/akraino/dashboard/landing.html b/src/templates/akraino/dashboard/landing.html index d7f434b..5533469 100644 --- a/src/templates/akraino/dashboard/landing.html +++ b/src/templates/akraino/dashboard/landing.html @@ -18,5 +18,6 @@ <p>To get started, book a pod below:</p> <a class="btn btnAkr btn-lg d-flex flex-column justify-content-center align-content-center border text-white p-4" href="/booking/quick/">Book a Pod</a> {% endblock btnGrp %} + {% block returningUsers %} {% endblock returningUsers %} diff --git a/src/templates/base/base.html b/src/templates/base/base.html index cc6d38d..3ecad1a 100644 --- a/src/templates/base/base.html +++ b/src/templates/base/base.html @@ -45,20 +45,49 @@ <i class="fas fa-caret-down rotate"></i> </a> <div class="dropdown-menu dropdown-menu-right"> - {% if user.is_authenticated %} + {% if LFID %} + {% if user.is_authenticated %} <a href="{% url 'account:settings' %}" class="text-dark dropdown-item"> <i class="fas fa-cog"></i> - Settings + Settings </a> - <a href="{% url 'account:logout' %}?next={{ request.path }}" class="text-dark dropdown-item"> + <a id="logout_btn" href="#" method="post" class="text-dark dropdown-item"> <i class="fas fa-sign-out-alt"></i> - Logout + Logout </a> - {% else %} - <a href="{% url 'account:login' %}" class="text-dark dropdown-item"> + <form id="logout_form" action="{% url 'oidc_logout' %}" method="post" style="visibility: hidden;"> + {% csrf_token %} + <input type="submit" value="logout"> + </form> + <script> + const logout_btn = document.getElementById("logout_btn"); + + const logout_form = document.getElementById("logout_form"); + + logout_btn.onclick = function() { logout_form.submit(); }; + </script> + {% else %} + <a href="{% url 'oidc_authentication_init' %}" class="text-dark dropdown-item"> <i class="fas fa-sign-in-alt"></i> - Login with Jira + Login with LFID </a> + {% endif %} + {% else %} + {% if user.is_authenticated %} + <a href="{% url 'account:settings' %}" class="text-dark dropdown-item"> + <i class="fas fa-cog"></i> + Settings + </a> + <a href="{% url 'account:logout' %}?next={{ request.path }}" class="text-dark dropdown-item"> + <i class="fas fa-sign-out-alt"></i> + Logout + </a> + {% else %} + <a href="{% url 'account:login' %}" class="text-dark dropdown-item"> + <i class="fas fa-sign-in-alt"></i> + Login with Jira + </a> + {% endif %} {% endif %} </div> </li> diff --git a/src/templates/base/dashboard/landing.html b/src/templates/base/dashboard/landing.html index ecb12c6..4ed2ec1 100644 --- a/src/templates/base/dashboard/landing.html +++ b/src/templates/base/dashboard/landing.html @@ -43,9 +43,15 @@ <div class="col-12 col-lg-6 mb-4"> <h2 class="border-bottom">Get Started</h2> {% if request.user.is_anonymous %} + {% if LFID %} + <h4 class="text-center"> + To get started, please log in with <a href="{% url 'oidc_authentication_init' %}">Linux Foundation ID</a> + </h4> + {% else %} <h4 class="text-center"> To get started, please log in with your <a href="/accounts/login">Linux Foundation Jira account</a> </h4> + {% endif %} {% else %} {% block btnGrp %} <p>To get started, book a server below:</p> diff --git a/src/templates/base/dashboard/login.html b/src/templates/base/dashboard/login.html index d3aa4ad..5af201a 100644 --- a/src/templates/base/dashboard/login.html +++ b/src/templates/base/dashboard/login.html @@ -1,8 +1,7 @@ {% extends "base.html" %} {% block content %} -<h3>You Must Login To Do That</h3> - -<a href="/accounts/login">Login Here</a> +<h3> You Must Login To Do That<h3> +<a href="{% url 'oidc_authentication_init' %}"> Login Here </a> {% endblock %} |