Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SAML2 auth #2511

Closed
wants to merge 4 commits into from
Closed
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
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ RUN echo Cloning branch $PG_BRANCH branch from $PG_GIT_URL \
FROM ubuntu:24.04

ENV WEBWORK_URL=/webwork2 \
WEBWORK_ROOT_URL=http://localhost::8080 \
WEBWORK_ROOT_URL=http://localhost:8080 \
WEBWORK_SMTP_SERVER=localhost \
WEBWORK_SMTP_SENDER=webwork@example.com \
WEBWORK_TIMEZONE=America/New_York \
Expand Down Expand Up @@ -190,6 +190,7 @@ RUN cpanm install -n \
DBD::MariaDB \
Perl::Tidy@20220613 \
Archive::Zip::SimpleZip \
Net::SAML2 \
&& rm -fr ./cpanm /root/.cpanm /tmp/*

# ==================================================================
Expand Down
1 change: 1 addition & 0 deletions DockerfileStage1
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ RUN cpanm install -n \
DBD::MariaDB \
Perl::Tidy@20220613 \
Archive::Zip::SimpleZip \
Net::SAML2 \
&& rm -fr ./cpanm /root/.cpanm /tmp/*

# ==================================================================
2 changes: 1 addition & 1 deletion DockerfileStage2
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ RUN echo Cloning branch $PG_BRANCH branch from $PG_GIT_URL \
FROM webwork-base:forWW219

ENV WEBWORK_URL=/webwork2 \
WEBWORK_ROOT_URL=http://localhost::8080 \
WEBWORK_ROOT_URL=http://localhost:8080 \
WEBWORK_SMTP_SERVER=localhost \
WEBWORK_SMTP_SENDER=webwork@example.com \
WEBWORK_TIMEZONE=America/New_York \
Expand Down
120 changes: 120 additions & 0 deletions conf/authen_saml2.dist.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
---
################################################################################
# Configuration for the Saml2 plugin
#
# To enable the Saml2 plugin, copy authen_saml2.dist.yml to authen_saml2.yml
#
# The Saml2 plugin uses the Net::SAML2 library, the library claims to be
# compatible with a wide range of SAML2 implementations, including Shibboleth.
################################################################################

# add this query to the end of a course url to skip the saml2 authen module
# and go to the next one, comment out to disable this feature
bypass_query: bypassSaml2
idp: # this is the central SAML2 server
# url where we can get the SAML2 metadata xml for the IdP
metadata_url: http://idp.docker:8180/simplesaml/module.php/saml/idp/metadata
sp: # this is the Webwork side
# also known as iss (issuer)
entity_id: http://localhost:8080/saml2
# endoints created by the plugin, relative to the webwork root url
route:
base: '/saml2' # prefix path for all URLs handled by the plugin
metadata: '/metadata' # actual path would be /saml2/metadata
# 'Assertion Consumer Service', basically handles the SAML response, plugin
# only supports a POST response (HTTP POST Binding)
acs:
post: '/acs/post'
# Ideally, there would be a way to have separate app info and org info but
# Net::SAML2's metadata generation doesn't seem to have that separation. So
# I've filled out the org info with app info instead.
org:
contact: 'webwork@example.edu'
name: 'webwork'
url: 'https://localhost:8080/'
display_name: 'WeBWorK'
# list of attributes that can be used as the username, each of them will be
# tried in turn to see if there's a matching user in the classlist. If no
# attributes are given, then we'll default to the NameID. Please use the
# attribute's OID
attributes:
- 'urn:oid:0.9.2342.19200300.100.1.1'
##############################################################################
# SECURITY WARNING
# For production, you MUST generate your own unique 'cert' and 'signing_key'.
# The examples below are publicly exposed and thus provides NO SECURITY.
##############################################################################
# Cert and key pairs can be generated using an openssl command such as:
# openssl req -newkey rsa:3072 -new -x509 -days 3652 -nodes -out webwork.crt -keyout webwork.pem
# Where webwork.crt contains the cert and webwork.pem contains the signing_key
cert: |
-----BEGIN CERTIFICATE-----
MIIE7zCCA1egAwIBAgIUIteyNYLSAiB0FcNl0GLJNYRppk8wDQYJKoZIhvcNAQEL
BQAwgYYxCzAJBgNVBAYTAkFBMQswCQYDVQQIDAJBQTEQMA4GA1UEBwwHRXhhbXBs
ZTEQMA4GA1UECgwHRXhhbXBsZTEQMA4GA1UECwwHRXhhbXBsZTEQMA4GA1UEAwwH
RXhhbXBsZTEiMCAGCSqGSIb3DQEJARYTZXhhbXBsZUBleGFtcGxlLmVkdTAeFw0y
NDA1MDMwMTA2MzNaFw0zNDA1MDMwMTA2MzNaMIGGMQswCQYDVQQGEwJBQTELMAkG
A1UECAwCQUExEDAOBgNVBAcMB0V4YW1wbGUxEDAOBgNVBAoMB0V4YW1wbGUxEDAO
BgNVBAsMB0V4YW1wbGUxEDAOBgNVBAMMB0V4YW1wbGUxIjAgBgkqhkiG9w0BCQEW
E2V4YW1wbGVAZXhhbXBsZS5lZHUwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGK
AoIBgQC45DCHUejzAeq+eVwEX5zSQWC+kqydEmoxpydT4YiSXnNeoNAkilKfHGOY
Uc4djwx148N14A+S0GCys2j3Ey2wuL7DSep5y1Z9Uxj6Ayg23XGIFFFJJLMy1Qfe
pjCcr1djPH9PpwglG1nTsiWqvHGGc3WWn1u6RfyrCf+jxbhygNRTA+LVPpqNvko6
MWKsbVLKrYMV2kPcQ0PQByNHJnjBy3KH2k99lS20h32sgHbgbVpJWdAWjeyJrOh9
aDt4/AfK90BvhkjF4BuQ+Jw5oIwMhbx7YmzIfiJmBLLaGjVRppuoAQtLX9uLst9l
aLZzaeutg+G3RUYcvDMlnP7cU8Sq4BD7uK0ChKxxCMFcihAhQ8wqCKncaaE9WqPs
CM16SB/6xptOxoLcg/5q3PJyUi2g4VDKXuQc6AURKIJxSM9nlrcv/R7fCFgk3Nj/
piWykDk6/BDWFpEHaj+NnFE9ZIxKr9CjTxdmqiDTyqSv50rNCjleyL/iASBTSCCF
OPVOYQECAwEAAaNTMFEwHQYDVR0OBBYEFGs8F3VIGSEk+DE2MBqqNKX6UuZTMB8G
A1UdIwQYMBaAFGs8F3VIGSEk+DE2MBqqNKX6UuZTMA8GA1UdEwEB/wQFMAMBAf8w
DQYJKoZIhvcNAQELBQADggGBAIpDktpfGH7ZqgdWvxbJrjekb1IyCGrWsHOYSjwM
+MxnhAA6oY63wC04a2i31zIMNOkY9F0tAdd4uDchxA9IWHqpb7t7zBlZdDabPPC3
WoDYnKhtZBULVVo7AvWO0UJGfZNJE393aKer3ePvfoG0OpCyrw4eFI/GCd4UjJBF
DnD7hvUxE7RRwOhbuYrtDRuB3Z7CeeP8o81eDVexyuBpM/9UQjYPqBBAfoeYKQzu
ZIhpGRWXw0ntH+EEOWagRXA5pRru61hteParZe4LBjPqisqN4Ek6ZR7MD9gB5xnt
Pn1BKRY08quFOZyaogzwfkYk5SCF8F8jBA8ZNAYwJWe1gtO3iw5vpUaQc2iCabvI
Y+Pc6qsSNwbkl7+sFrVHzI9QZVyz1cARUXxvrgGNLBkYtprkG91k6mCjX90cQspb
ZwHixcQyCNv+4H738e99h/Wf0YzjxFjDKrbGoosYBzWAsYYtzrtsBvw3SJMTXIh7
OvFMA+rbIL8XWs8oNmZDDh8g0A==
-----END CERTIFICATE-----
signing_key: |
-----BEGIN PRIVATE KEY-----
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
dzDq+xUD8nHpKM33A2EaUFY=
-----END PRIVATE KEY-----
43 changes: 42 additions & 1 deletion docker-config/docker-compose.dist.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
version: '3.5'
services:
db:
image: mariadb:10.4
Expand Down Expand Up @@ -252,6 +251,48 @@ services:
#ports:
# - "6311:6311"

# saml2 dev use only, separate profile from the other services so it doesn't
# start in normal usage. Use "docker compose --profile saml2dev up" to start.
idp:
build:
context: ./docker-config/idp/ # SimpleSAMLphp based IDP
profiles:
- saml2dev
ports:
- '8180:80'
environment:
SP_METADATA_URL: 'http://app.docker:8080/saml2/metadata'
# the healthcheck url is simplesamlphp's url for triggering cron jobs, the
# cron job it'll trigger is to automatically grab webwork sp's metadata
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost/simplesaml/module.php/cron/run/docker/healthcheck']
start_period: 1m
start_interval: 15s
interval: 1h
retries: 1
timeout: 10s
# Send internal docker traffic for the idp external port to the idp internal
# port. Needed so the webwork saml2 plugin can request the idp metadata.
socat-idp:
image: alpine/socat:1.8.0.0
profiles:
- saml2dev
command: 'TCP-LISTEN:8180,fork,reuseaddr TCP:idp:80'
networks:
default:
aliases:
- idp.docker
# same port redirect so the idp can get the webwork saml2 plugin metadata
socat-app:
image: alpine/socat:1.8.0.0
profiles:
- saml2dev
command: 'TCP-LISTEN:8080,fork,reuseaddr TCP:app:8080'
networks:
default:
aliases:
- app.docker

volumes:
oplVolume:
driver: local
Expand Down
36 changes: 36 additions & 0 deletions docker-config/idp/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# actual image we'll run in the end
FROM php:8.3-apache
WORKDIR /var/www

# Install composer & php extension installer
COPY --from=composer/composer:2-bin /composer /usr/bin/composer
COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/

RUN apt-get update && \
apt-get -y install git curl vim && \
install-php-extensions ldap zip

# dirs used by simplesamlphp needs to be accessible by apache user
RUN mkdir simplesamlphp/ /var/cache/simplesamlphp
RUN chown www-data. simplesamlphp/ /var/cache/simplesamlphp
# Composer doesn't like to be root, so we'll run the rest as the apache user
USER www-data

# Install simplesamlphp
ARG SIMPLESAMLPHP_TAG=v2.2.1
RUN git clone --branch $SIMPLESAMLPHP_TAG https://github.com/simplesamlphp/simplesamlphp.git
WORKDIR /var/www/simplesamlphp

# Generate certs
RUN cd cert/ && \
openssl req -newkey rsa:3072 -new -x509 -days 3652 -nodes -out server.crt -keyout server.pem -subj "/C=CA/SP=BC/L=Vancouver/O=UBC/CN=idp.docker"

# Use composer to install dependencies
RUN composer install && \
composer require simplesamlphp/simplesamlphp-module-metarefresh

# Copy config files
COPY ./config/ config/
COPY ./metadata/ metadata/

COPY ./apache.conf /etc/apache2/sites-available/000-default.conf
38 changes: 38 additions & 0 deletions docker-config/idp/apache.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<VirtualHost *:80>
# The ServerName directive sets the request scheme, hostname and port that
# the server uses to identify itself. This is used when creating
# redirection URLs. In the context of virtual hosts, the ServerName
# specifies what hostname must appear in the request's Host: header to
# match this virtual host. For the default virtual host (this file) this
# value is not decisive as it is used as a last resort host regardless.
# However, you must set it for any further virtual host explicitly.
#ServerName www.example.com

ServerAdmin webmaster@localhost
DocumentRoot /var/www/simplesamlphp

# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
# error, crit, alert, emerg.
# It is also possible to configure the loglevel for particular
# modules, e.g.
#LogLevel info ssl:warn

ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined

# For most configuration files from conf-available/, which are
# enabled or disabled at a global level, it is possible to
# include a line for only one particular virtual host. For example the
# following line enables the CGI configuration for this host only
# after it has been globally disabled with "a2disconf".
#Include conf-available/serve-cgi-bin.conf

SetEnv SIMPLESAMLPHP_CONFIG_DIR /var/www/simplesamlphp/config

Alias /simplesaml /var/www/simplesamlphp/public

<Directory /var/www/simplesamlphp/public>
Require all granted
</Directory>

</VirtualHost>
Loading