diff --git a/third_party/apereo-cas/overlay/.dockerignore b/third_party/apereo-cas/overlay/.dockerignore
new file mode 100644
index 000000000..5e04587dd
--- /dev/null
+++ b/third_party/apereo-cas/overlay/.dockerignore
@@ -0,0 +1,7 @@
+target/**
+build/**
+bin/**
+.idea/**
+.history/**
+.github/**
+.git/**
diff --git a/third_party/apereo-cas/overlay/.gitattributes b/third_party/apereo-cas/overlay/.gitattributes
new file mode 100644
index 000000000..8fc5677e1
--- /dev/null
+++ b/third_party/apereo-cas/overlay/.gitattributes
@@ -0,0 +1,6 @@
+# Set line endings to LF, even on Windows. Otherwise, execution within Docker fails.
+# See https://help.github.com/articles/dealing-with-line-endings/
+*.sh text eol=lf
+gradlew text eol=lf
+*.cmd text eol=crlf
+*.bat text eol=crlf
diff --git a/third_party/apereo-cas/overlay/.github/FUNDING.yml b/third_party/apereo-cas/overlay/.github/FUNDING.yml
new file mode 100644
index 000000000..30b54fb73
--- /dev/null
+++ b/third_party/apereo-cas/overlay/.github/FUNDING.yml
@@ -0,0 +1 @@
+custom: ['https://www.apereo.org/content/apereo-membership']
diff --git a/third_party/apereo-cas/overlay/.github/renovate.json b/third_party/apereo-cas/overlay/.github/renovate.json
new file mode 100644
index 000000000..58fa77f03
--- /dev/null
+++ b/third_party/apereo-cas/overlay/.github/renovate.json
@@ -0,0 +1,11 @@
+{
+ "extends": [
+ "config:base",
+ ":preserveSemverRanges",
+ ":rebaseStalePrs",
+ ":disableRateLimiting",
+ ":semanticCommits",
+ ":semanticCommitTypeAll(renovatebot)"
+ ],
+ "labels": ["dependencies", "bot"]
+}
diff --git a/third_party/apereo-cas/overlay/.gitignore b/third_party/apereo-cas/overlay/.gitignore
new file mode 100755
index 000000000..45840be34
--- /dev/null
+++ b/third_party/apereo-cas/overlay/.gitignore
@@ -0,0 +1,22 @@
+.classpath
+!/.project
+.project
+.settings
+.history
+.vscode
+target/
+.idea/
+.DS_Store
+.idea
+overlays/
+.gradle/
+build/
+log/
+bin/
+*.war
+*.iml
+*.log
+tmp/
+./apache-tomcat
+apache-tomcat.zip
+config-metadata.properties
diff --git a/third_party/apereo-cas/overlay/.mergify.yml b/third_party/apereo-cas/overlay/.mergify.yml
new file mode 100644
index 000000000..4fcbdbe4a
--- /dev/null
+++ b/third_party/apereo-cas/overlay/.mergify.yml
@@ -0,0 +1,32 @@
+#
+# Licensed to Apereo under one or more contributor license
+# agreements. See the NOTICE file distributed with this work
+# for additional information regarding copyright ownership.
+# Apereo licenses this file to you under the Apache License,
+# Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a
+# copy of the License at the following location:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+pull_request_rules:
+- name: automatic merge by dependabot
+ conditions:
+ - status-success=continuous-integration/travis-ci/pr
+ - status-success=WIP
+ - "#changes-requested-reviews-by=0"
+ - base=master
+ - label=dependencies
+ actions:
+ merge:
+ method: merge
+ strict: true
+ delete_head_branch:
\ No newline at end of file
diff --git a/third_party/apereo-cas/overlay/.travis.yml b/third_party/apereo-cas/overlay/.travis.yml
new file mode 100644
index 000000000..8347dd171
--- /dev/null
+++ b/third_party/apereo-cas/overlay/.travis.yml
@@ -0,0 +1,62 @@
+language: java
+sudo: required
+dist: trusty
+services:
+ - docker
+branches:
+ only:
+ - master
+before_cache:
+ - rm -rf $HOME/.gradle/caches/5.*/
+ - rm -rf $HOME/.gradle/caches/4.*/
+ - rm -fr $HOME/.gradle/caches/*/plugin-resolution/
+ - find ~/.gradle/caches/ -name "*.lock" -type f -delete
+cache:
+ bundler: false
+ cargo: false
+ directories:
+ - $HOME/.m2
+ - $HOME/.npm/
+ - $HOME/.gradle/caches/
+ - $HOME/.gradle/wrapper/
+env:
+ global:
+ - JAVA_OPTS="-Xms512m -Xmx4048m -Xss128m -XX:ReservedCodeCacheSize=512m -XX:+UseG1GC -Xverify:none -server"
+ - GRADLE_OPTS="-Xms512m -Xmx1024m -Xss128m -XX:ReservedCodeCacheSize=512m -XX:+UseG1GC -Xverify:none -server"
+jdk:
+- openjdk11
+before_install:
+- echo -e "Configuring Gradle wrapper...\n"
+- mkdir -p ~/.gradle && echo "org.gradle.daemon=false" >> ~/.gradle/gradle.properties
+- chmod -R 777 ./gradlew
+- chmod -R 777 *.sh
+install: true
+stages:
+ - build
+ - validate
+ - docker
+jobs:
+ include:
+ - stage: build
+ script: ./gradlew clean build --stacktrace --no-daemon --refresh-dependencies -Dorg.gradle.internal.http.socketTimeout=600000 -Dorg.gradle.internal.http.connectionTimeout=600000
+ name: "Build CAS"
+ ############################################
+ - stage: validate
+ script: ./gradlew downloadShell
+ name: "Download CAS Shell"
+ - stage: validate
+ script: ./gradlew listTemplateViews
+ name: "List CAS Template Views"
+ - stage: validate
+ script: ./gradlew explodeWar
+ name: "Unzip CAS Web Application"
+ ############################################
+ - stage: docker
+ script: ./gradlew build jibDockerBuild --stacktrace --no-daemon --refresh-dependencies
+ name: "Build Docker Image via Jib"
+ - stage: docker
+ script: docker-compose build
+ name: "Build Docker Image via Docker Compose"
+ - stage: docker
+ script: ./docker-build.sh
+ name: "Build Docker Image"
\ No newline at end of file
diff --git a/third_party/apereo-cas/overlay/Dockerfile b/third_party/apereo-cas/overlay/Dockerfile
new file mode 100644
index 000000000..17ab5648b
--- /dev/null
+++ b/third_party/apereo-cas/overlay/Dockerfile
@@ -0,0 +1,40 @@
+FROM adoptopenjdk/openjdk11:alpine-slim AS overlay
+
+RUN mkdir -p cas-overlay
+COPY ./src cas-overlay/src/
+COPY ./gradle/ cas-overlay/gradle/
+COPY ./gradlew ./settings.gradle ./build.gradle ./gradle.properties /cas-overlay/
+
+RUN mkdir -p ~/.gradle \
+ && echo "org.gradle.daemon=false" >> ~/.gradle/gradle.properties \
+ && echo "org.gradle.configureondemand=true" >> ~/.gradle/gradle.properties \
+ && cd cas-overlay \
+ && chmod 750 ./gradlew \
+ && ./gradlew --version;
+
+RUN cd cas-overlay \
+ && ./gradlew clean build --parallel --no-daemon;
+
+FROM adoptopenjdk/openjdk11:alpine-jre AS cas
+
+LABEL "Organization"="Apereo"
+LABEL "Description"="Apereo CAS"
+
+RUN cd / \
+ && mkdir -p /etc/cas/config \
+ && mkdir -p /etc/cas/services \
+ && mkdir -p /etc/cas/saml \
+ && mkdir -p cas-overlay;
+
+COPY etc/cas/ /etc/cas/
+COPY etc/cas/config/ /etc/cas/config/
+COPY etc/cas/services/ /etc/cas/services/
+COPY etc/cas/saml/ /etc/cas/saml/
+COPY --from=overlay cas-overlay/build/libs/cas.war cas-overlay/
+
+EXPOSE 8080 8443
+
+ENV PATH $PATH:$JAVA_HOME/bin:.
+
+WORKDIR cas-overlay
+ENTRYPOINT ["java", "-server", "-noverify", "-Xmx2048M", "-jar", "cas.war"]
diff --git a/third_party/apereo-cas/overlay/LICENSE.txt b/third_party/apereo-cas/overlay/LICENSE.txt
new file mode 100644
index 000000000..d64569567
--- /dev/null
+++ b/third_party/apereo-cas/overlay/LICENSE.txt
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/third_party/apereo-cas/overlay/README.md b/third_party/apereo-cas/overlay/README.md
new file mode 100644
index 000000000..ec8d96483
--- /dev/null
+++ b/third_party/apereo-cas/overlay/README.md
@@ -0,0 +1,146 @@
+CAS Overlay Template [![Build Status](https://travis-ci.org/apereo/cas-overlay-template.svg?branch=master)](https://travis-ci.org/apereo/cas-overlay-template)
+=======================
+
+Generic CAS WAR overlay to exercise the latest versions of CAS. This overlay could be freely used as a starting template for local CAS war overlays.
+
+# Versions
+
+- CAS `6.2.x`
+- JDK `11`
+
+# Overview
+
+To build the project, use:
+
+```bash
+# Use --refresh-dependencies to force-update SNAPSHOT versions
+./gradlew[.bat] clean build
+```
+
+To see what commands are available to the build script, run:
+
+```bash
+./gradlew[.bat] tasks
+```
+
+To launch into the CAS command-line shell:
+
+```bash
+./gradlew[.bat] downloadShell runShell
+```
+
+To fetch and overlay a CAS resource or view, use:
+
+```bash
+./gradlew[.bat] getResource -PresourceName=[resource-name]
+```
+
+To list all available CAS views and templates:
+
+```bash
+./gradlew[.bat] listTemplateViews
+```
+
+To unzip and explode the CAS web application file and the internal resources jar:
+
+```bash
+./gradlew[.bat] explodeWar
+```
+
+# Configuration
+
+- The `etc` directory contains the configuration files and directories that need to be copied to `/etc/cas/config`.
+
+```bash
+./gradlew[.bat] copyCasConfiguration
+```
+
+- The specifics of the build are controlled using the `gradle.properties` file.
+
+## Adding Modules
+
+CAS modules may be specified under the `dependencies` block of the [Gradle build script](build.gradle):
+
+```gradle
+dependencies {
+ compile "org.apereo.cas:cas-server-some-module:${project.casVersion}"
+ ...
+}
+```
+
+To collect the list of all project modules and dependencies:
+
+```bash
+./gradlew[.bat] allDependencies
+```
+
+### Clear Gradle Cache
+
+If you need to, on Linux/Unix systems, you can delete all the existing artifacts (artifacts and metadata) Gradle has downloaded using:
+
+```bash
+# Only do this when absolutely necessary
+rm -rf $HOME/.gradle/caches/
+```
+
+Same strategy applies to Windows too, provided you switch `$HOME` to its equivalent in the above command.
+
+# Deployment
+
+- Create a keystore file `thekeystore` under `/etc/cas`. Use the password `changeit` for both the keystore and the key/certificate entries. This can either be done using the JDK's `keytool` utility or via the following command:
+
+```bash
+./gradlew[.bat] createKeystore
+```
+
+- Ensure the keystore is loaded up with keys and certificates of the server.
+
+On a successful deployment via the following methods, CAS will be available at:
+
+* `https://cas.server.name:8443/cas`
+
+## Executable WAR
+
+Run the CAS web application as an executable WAR:
+
+```bash
+./gradlew[.bat] run
+```
+
+Debug the CAS web application as an executable WAR:
+
+```bash
+./gradlew[.bat] debug
+```
+
+Run the CAS web application as a *standalone* executable WAR:
+
+```bash
+./gradlew[.bat] clean executable
+```
+
+## External
+
+Deploy the binary web application file `cas.war` after a successful build to a servlet container of choice.
+
+## Docker
+
+The following strategies outline how to build and deploy CAS Docker images.
+
+### Jib
+
+The overlay embraces the [Jib Gradle Plugin](https://github.com/GoogleContainerTools/jib) to provide easy-to-use out-of-the-box tooling for building CAS docker images. Jib is an open-source Java containerizer from Google that lets Java developers build containers using the tools they know. It is a container image builder that handles all the steps of packaging your application into a container image. It does not require you to write a Dockerfile or have Docker installed, and it is directly integrated into the overlay.
+
+```bash
+./gradlew build jibDockerBuild
+```
+
+### Dockerfile
+
+You can also use the native Docker tooling and the provided `Dockerfile` to build and run CAS.
+
+```bash
+chmod +x *.sh
+./docker-build.sh
+./docker-run.sh
+```
diff --git a/third_party/apereo-cas/overlay/build.gradle b/third_party/apereo-cas/overlay/build.gradle
new file mode 100644
index 000000000..79a7e7c1b
--- /dev/null
+++ b/third_party/apereo-cas/overlay/build.gradle
@@ -0,0 +1,111 @@
+buildscript {
+ repositories {
+ mavenLocal()
+ gradlePluginPortal()
+ mavenCentral()
+ jcenter()
+ maven {
+ url "https://repo.spring.io/libs-milestone"
+ mavenContent { releasesOnly() }
+ }
+ maven {
+ url "https://repo.spring.io/libs-snapshot"
+ mavenContent { snapshotsOnly() }
+ }
+ maven {
+ url "https://plugins.gradle.org/m2/"
+ mavenContent { releasesOnly() }
+ }
+ }
+ dependencies {
+ classpath "de.undercouch:gradle-download-task:${project.gradleDownloadTaskVersion}"
+ classpath "org.springframework.boot:spring-boot-gradle-plugin:${project.springBootVersion}"
+ classpath "gradle.plugin.com.google.cloud.tools:jib-gradle-plugin:${project.jibVersion}"
+ classpath "io.freefair.gradle:maven-plugin:${project.gradleMavenPluginVersion}"
+ classpath "io.freefair.gradle:lombok-plugin:${project.gradleLombokPluginVersion}"
+ }
+}
+
+repositories {
+ mavenLocal()
+ mavenCentral()
+ jcenter()
+ maven {
+ url "https://oss.sonatype.org/content/repositories/snapshots"
+ mavenContent { snapshotsOnly() }
+ }
+ maven {
+ mavenContent { releasesOnly() }
+ url "https://build.shibboleth.net/nexus/content/repositories/releases/"
+ }
+ maven {
+ mavenContent { releasesOnly() }
+ url "https://repo.spring.io/milestone/"
+ }
+ maven {
+ url "https://repo.spring.io/snapshot/"
+ mavenContent { snapshotsOnly() }
+ }
+ maven {
+ mavenContent { snapshotsOnly() }
+ url "https://oss.jfrog.org/artifactory/oss-snapshot-local"
+ }
+}
+
+def casServerVersion = project.'cas.version'
+def casWebApplicationBinaryName = "cas.war"
+
+project.ext."casServerVersion" = casServerVersion
+project.ext."casWebApplicationBinaryName" = casWebApplicationBinaryName
+
+apply plugin: "io.freefair.war-overlay"
+apply plugin: "io.freefair.lombok"
+apply from: rootProject.file("gradle/tasks.gradle")
+
+apply plugin: "war"
+apply plugin: "eclipse"
+apply plugin: "idea"
+
+apply from: rootProject.file("gradle/springboot.gradle")
+apply from: rootProject.file("gradle/dockerjib.gradle")
+
+dependencies {
+ // Other CAS dependencies/modules may be listed here...
+ // implementation "org.apereo.cas:cas-server-support-json-service-registry:${casServerVersion}"
+}
+
+tasks.findByName("jibDockerBuild")
+ .dependsOn(copyWebAppIntoJib, copyConfigIntoJib)
+ .finalizedBy(deleteWebAppFromJib)
+
+tasks.findByName("jib")
+ .dependsOn(copyWebAppIntoJib, copyConfigIntoJib)
+ .finalizedBy(deleteWebAppFromJib)
+
+configurations.all {
+ resolutionStrategy {
+ cacheChangingModulesFor 0, "seconds"
+ cacheDynamicVersionsFor 0, "seconds"
+
+ preferProjectModules()
+
+ def failIfConflict = project.hasProperty("failOnVersionConflict") && Boolean.valueOf(project.getProperty("failOnVersionConflict"))
+ if (failIfConflict) {
+ failOnVersionConflict()
+ }
+ }
+}
+
+eclipse {
+ classpath {
+ downloadSources = true
+ downloadJavadoc = true
+ }
+}
+
+idea {
+ module {
+ downloadJavadoc = true
+ downloadSources = true
+ }
+}
diff --git a/third_party/apereo-cas/overlay/docker-build.sh b/third_party/apereo-cas/overlay/docker-build.sh
new file mode 100755
index 000000000..dc098ade9
--- /dev/null
+++ b/third_party/apereo-cas/overlay/docker-build.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+image_tag=(`cat gradle.properties | grep "cas.version" | cut -d= -f2`)
+
+echo "Building CAS docker image tagged as [v$image_tag]"
+# read -p "Press [Enter] to continue..." any_key;
+
+docker build --tag="apereo/cas:v$image_tag" . \
+ && echo "Built CAS image successfully tagged as apereo/cas:v$image_tag" \
+ && docker images "apereo/cas:v$image_tag"
\ No newline at end of file
diff --git a/third_party/apereo-cas/overlay/docker-compose.yml b/third_party/apereo-cas/overlay/docker-compose.yml
new file mode 100644
index 000000000..8f2e6ca7c
--- /dev/null
+++ b/third_party/apereo-cas/overlay/docker-compose.yml
@@ -0,0 +1,7 @@
+version: '3'
+services:
+ cas:
+ build: .
+ ports:
+ - "8443:8443"
+ - "8080:8080"
\ No newline at end of file
diff --git a/third_party/apereo-cas/overlay/docker-push.sh b/third_party/apereo-cas/overlay/docker-push.sh
new file mode 100755
index 000000000..ca7b784e6
--- /dev/null
+++ b/third_party/apereo-cas/overlay/docker-push.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+read -p "Docker username: " docker_user
+read -s -p "Docker password: " docker_psw
+
+echo "$docker_psw" | docker login --username "$docker_user" --password-stdin
+
+image_tag=(`cat gradle.properties | grep "cas.version" | cut -d= -f2`)
+
+echo "Pushing CAS docker image tagged as v$image_tag to apereo/cas..."
+docker push apereo/cas:"v$image_tag" \
+ && echo "Pushed apereo/cas:v$image_tag successfully.";
\ No newline at end of file
diff --git a/third_party/apereo-cas/overlay/docker-run.sh b/third_party/apereo-cas/overlay/docker-run.sh
new file mode 100755
index 000000000..6b4ce9755
--- /dev/null
+++ b/third_party/apereo-cas/overlay/docker-run.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+docker stop cas > /dev/null 2>&1
+docker rm cas > /dev/null 2>&1
+image_tag=(`cat gradle.properties | grep "cas.version" | cut -d= -f2`)
+docker run -d -p 8080:8080 -p 8443:8443 --name="cas" apereo/cas:"v${image_tag}"
+docker logs -f cas
\ No newline at end of file
diff --git a/third_party/apereo-cas/overlay/etc/cas/config/cas.properties b/third_party/apereo-cas/overlay/etc/cas/config/cas.properties
new file mode 100644
index 000000000..40cd89bbe
--- /dev/null
+++ b/third_party/apereo-cas/overlay/etc/cas/config/cas.properties
@@ -0,0 +1,6 @@
+cas.server.name=https://cas.example.org:8443
+cas.server.prefix=${cas.server.name}/cas
+
+logging.config=file:/etc/cas/config/log4j2.xml
+
+# cas.authn.accept.users=
diff --git a/third_party/apereo-cas/overlay/etc/cas/config/log4j2.xml b/third_party/apereo-cas/overlay/etc/cas/config/log4j2.xml
new file mode 100644
index 000000000..685dfab24
--- /dev/null
+++ b/third_party/apereo-cas/overlay/etc/cas/config/log4j2.xml
@@ -0,0 +1,119 @@
+
+
+
+
+ /var/log
+
+ info
+ warn
+ info
+ warn
+ debug
+ warn
+ warn
+ warn
+ warn
+ warn
+ warn
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/third_party/apereo-cas/overlay/etc/cas/saml/.gitkeep b/third_party/apereo-cas/overlay/etc/cas/saml/.gitkeep
new file mode 100644
index 000000000..882c99944
--- /dev/null
+++ b/third_party/apereo-cas/overlay/etc/cas/saml/.gitkeep
@@ -0,0 +1 @@
+This directory is references in the Dockerfile so it needs to be here.
\ No newline at end of file
diff --git a/third_party/apereo-cas/overlay/etc/cas/services/.donotdel b/third_party/apereo-cas/overlay/etc/cas/services/.donotdel
new file mode 100644
index 000000000..e69de29bb
diff --git a/third_party/apereo-cas/overlay/etc/cas/thekeystore b/third_party/apereo-cas/overlay/etc/cas/thekeystore
new file mode 100644
index 000000000..78f49baf7
Binary files /dev/null and b/third_party/apereo-cas/overlay/etc/cas/thekeystore differ
diff --git a/third_party/apereo-cas/overlay/gradle.properties b/third_party/apereo-cas/overlay/gradle.properties
new file mode 100644
index 000000000..f49d921e1
--- /dev/null
+++ b/third_party/apereo-cas/overlay/gradle.properties
@@ -0,0 +1,28 @@
+# Versions
+cas.version=6.2.0
+springBootVersion=2.2.8.RELEASE
+
+# Use -jetty, -undertow to other containers
+# Or blank if you want to deploy to an external container
+appServer=-tomcat
+executable=false
+
+tomcatVersion=9.0.36
+
+group=org.apereo.cas
+sourceCompatibility=11
+targetCompatibility=11
+
+jibVersion=2.4.0
+
+# Location of the downloaded CAS shell JAR
+shellDir=build/libs
+ivyVersion=2.4.0
+gradleDownloadTaskVersion=3.4.3
+gradleMavenPluginVersion=4.1.5
+gradleLombokPluginVersion=4.1.5
+
+# use without "-slim" in tag name if you want tools like jstack, adds about 100MB to image size
+# (https://hub.docker.com/r/adoptopenjdk/openjdk11/tags/)
+baseDockerImage=adoptopenjdk/openjdk11:alpine-jre
+allowInsecureRegistries=false
diff --git a/third_party/apereo-cas/overlay/gradle/dockerjib.gradle b/third_party/apereo-cas/overlay/gradle/dockerjib.gradle
new file mode 100644
index 000000000..dbadd5aa1
--- /dev/null
+++ b/third_party/apereo-cas/overlay/gradle/dockerjib.gradle
@@ -0,0 +1,52 @@
+apply plugin: "com.google.cloud.tools.jib"
+
+jib {
+ from {
+ image = project.baseDockerImage
+ }
+ to {
+ image = "${project.group}/${project.name}"
+ /**
+ ecr-login: Amazon Elastic Container Registry (ECR)
+ gcr: Google Container Registry (GCR)
+ osxkeychain: Docker Hub
+ */
+ credHelper = "osxkeychain"
+ /**
+ auth {
+ username = "*******"
+ password = "*******"
+ }
+ */
+ tags = ["v" + casServerVersion]
+ }
+ container {
+ creationTime = "USE_CURRENT_TIMESTAMP"
+ entrypoint = ['docker/entrypoint.sh']
+ ports = ['80', '443', '8080', '8443']
+ labels = [version:casServerVersion, name:project.name, group:project.group]
+ }
+ extraDirectories {
+ paths = 'src/main/jib'
+ permissions = [
+ '/docker/entrypoint.sh': '755'
+ ]
+ }
+ allowInsecureRegistries = project.allowInsecureRegistries
+}
+
+task copyWebAppIntoJib(type: Copy, group: "Docker", description: "Copy the web application into Docker image") {
+ dependsOn build
+ from "build/libs/${casWebApplicationBinaryName}"
+ into "src/main/jib/docker/cas/war"
+}
+
+task copyConfigIntoJib(type: Copy, group: "Docker", description: "Copy the CAS configuration into Docker image") {
+ dependsOn build
+ from "etc/cas"
+ into "src/main/jib/docker/cas"
+}
+
+task deleteWebAppFromJib(type: Delete, group: "Docker", description: "Explodes the CAS web application archive") {
+ delete "src/main/jib/docker/cas"
+}
\ No newline at end of file
diff --git a/third_party/apereo-cas/overlay/gradle/springboot.gradle b/third_party/apereo-cas/overlay/gradle/springboot.gradle
new file mode 100644
index 000000000..79804b18e
--- /dev/null
+++ b/third_party/apereo-cas/overlay/gradle/springboot.gradle
@@ -0,0 +1,101 @@
+apply plugin: "org.springframework.boot"
+
+configurations {
+ bootRunConfig.extendsFrom compileClasspath
+}
+
+dependencies {
+ bootRunConfig "org.apereo.cas:cas-server-webapp-init:${casServerVersion}"
+ bootRunConfig "org.apereo.cas:cas-server-webapp-tomcat:${casServerVersion}"
+ bootRunConfig "org.springframework.boot:spring-boot-devtools:${project.springBootVersion}"
+}
+
+sourceSets {
+ bootRunSources {
+ resources {
+ srcDirs new File("//etc/cas/templates/"),
+ new File("${project.getProjectDir()}/src/main/resources/")
+ }
+ }
+}
+
+bootRun {
+ classpath = configurations.bootRunConfig + sourceSets.main.compileClasspath + sourceSets.main.runtimeClasspath
+ doFirst {
+ sourceResources sourceSets.bootRunSources
+ systemProperties = System.properties
+ }
+
+ def list = []
+ list.add("-XX:TieredStopAtLevel=1")
+ list.add("-Xverify:none")
+ list.add("--add-modules")
+ list.add("java.se")
+ list.add("--add-exports")
+ list.add("java.base/jdk.internal.ref=ALL-UNNAMED")
+ list.add("--add-opens")
+ list.add("java.base/java.lang=ALL-UNNAMED")
+ list.add("--add-opens")
+ list.add("java.base/java.nio=ALL-UNNAMED")
+ list.add("--add-opens")
+ list.add("java.base/sun.nio.ch=ALL-UNNAMED")
+ list.add("--add-opens")
+ list.add("java.management/sun.management=ALL-UNNAMED")
+ list.add("--add-opens")
+ list.add("jdk.management/com.sun.management.internal=ALL-UNNAMED")
+
+ list.add("-XX:+UnlockExperimentalVMOptions")
+ list.add("-XX:+EnableJVMCI")
+ list.add("-XX:+UseJVMCICompiler")
+
+ list.add("-Xrunjdwp:transport=dt_socket,address=5000,server=y,suspend=n")
+
+ jvmArgs = list
+
+ def appArgList = []
+ args = appArgList
+}
+
+springBoot {
+ buildInfo()
+ mainClassName = "org.apereo.cas.web.CasWebApplication"
+}
+
+bootWar {
+ def executable = project.hasProperty("executable") && Boolean.valueOf(project.getProperty("executable"))
+ if (executable) {
+ logger.info "Including launch script for executable WAR artifact"
+ launchScript()
+ } else {
+ logger.info "WAR artifact is not marked as an executable"
+ }
+ archiveName "${casWebApplicationBinaryName}"
+ baseName "cas"
+ excludeDevtools = false
+
+ entryCompression = ZipEntryCompression.STORED
+ /*
+ attachClasses = true
+ classesClassifier = 'classes'
+ archiveClasses = true
+ */
+ overlays {
+ /*
+ https://docs.freefair.io/gradle-plugins/current/reference/#_io_freefair_war_overlay
+ Note: The "excludes" property is only for files in the war dependency.
+ If a jar is excluded from the war, it could be brought back into the final war as a dependency
+ of non-war dependencies. Those should be excluded via normal gradle dependency exclusions.
+ */
+ cas {
+ from "org.apereo.cas:cas-server-webapp${project.appServer}:${casServerVersion}@war"
+ provided = false
+ /*
+ excludes = ["WEB-INF/lib/somejar-1.0*"]
+ enableCompilation = true
+ includes = ["*.xyz"]
+ targetPath = "sub-path/bar"
+ skip = false
+ */
+ }
+ }
+}
diff --git a/third_party/apereo-cas/overlay/gradle/tasks.gradle b/third_party/apereo-cas/overlay/gradle/tasks.gradle
new file mode 100644
index 000000000..40fdac0b1
--- /dev/null
+++ b/third_party/apereo-cas/overlay/gradle/tasks.gradle
@@ -0,0 +1,349 @@
+import org.apache.ivy.util.url.ApacheURLLister
+import org.apache.tools.ant.taskdefs.condition.Os
+import org.gradle.internal.logging.text.StyledTextOutputFactory
+
+import java.nio.file.Files
+import java.nio.file.Paths
+import java.nio.file.StandardCopyOption
+
+import static org.gradle.internal.logging.text.StyledTextOutput.Style
+
+buildscript {
+ repositories {
+ mavenLocal()
+ mavenCentral()
+ jcenter()
+ maven {
+ url "https://oss.sonatype.org/content/repositories/snapshots"
+ mavenContent { snapshotsOnly() }
+ }
+ }
+
+ dependencies {
+ classpath "org.apache.ivy:ivy:${project.ivyVersion}"
+ classpath "org.apereo.cas:cas-server-core-api-configuration-model:${project.'cas.version'}"
+ classpath "org.apereo.cas:cas-server-core-configuration-metadata-repository:${project.'cas.version'}"
+ }
+}
+
+apply plugin: "de.undercouch.download"
+
+def tomcatDirectory = "${buildDir}/apache-tomcat-${tomcatVersion}"
+project.ext."tomcatDirectory" = tomcatDirectory
+
+def explodedDir = "${buildDir}/cas"
+def explodedResourcesDir = "${buildDir}/cas-resources"
+
+def resourcesJarName = "cas-server-webapp-resources"
+def templateViewsJarName = "cas-server-support-thymeleaf"
+
+task copyCasConfiguration(type: Copy, group: "CAS", description: "Copy the CAS configuration from this project to /etc/cas/config") {
+ from "etc/cas/config"
+ into new File('/etc/cas/config').absolutePath
+ doFirst {
+ new File('/etc/cas/config').mkdirs()
+ }
+}
+
+task explodeWarOnly(type: Copy, group: "CAS", description: "Explodes the CAS web application archive") {
+ dependsOn 'build'
+ from zipTree("build/libs/${casWebApplicationBinaryName}")
+ into explodedDir
+ doLast {
+ println "Exploded WAR into ${explodedDir}"
+ }
+}
+
+task explodeWar(type: Copy, group: "CAS", description: "Explodes the CAS archive and resources jar from the CAS web application archive") {
+ dependsOn explodeWarOnly
+ from zipTree("${explodedDir}/WEB-INF/lib/${templateViewsJarName}-${casServerVersion}.jar")
+ into explodedResourcesDir
+
+ from zipTree("${explodedDir}/WEB-INF/lib/${resourcesJarName}-${casServerVersion}.jar")
+ into explodedResourcesDir
+
+ doLast {
+ println "Exploded WAR resources into ${explodedResourcesDir}"
+ }
+}
+
+task run(group: "build", description: "Run the CAS web application in embedded container mode") {
+ dependsOn 'build'
+ doLast {
+ def casRunArgs = Arrays.asList("-server -noverify -Xmx2048M -XX:+TieredCompilation -XX:TieredStopAtLevel=1".split(" "))
+ javaexec {
+ main = "-jar"
+ jvmArgs = casRunArgs
+ args = ["build/libs/${casWebApplicationBinaryName}"]
+ systemProperties = System.properties
+ logger.info "Started ${commandLine}"
+ }
+ }
+}
+
+task setExecutable(group: "CAS", description: "Configure the project to run in executable mode") {
+ doFirst {
+ project.setProperty("executable", "true")
+ logger.info "Configuring the project as executable"
+ }
+}
+
+task executable(type: Exec, group: "CAS", description: "Run the CAS web application in standalone executable mode") {
+ dependsOn setExecutable, 'build'
+ doFirst {
+ workingDir "."
+ if (!Os.isFamily(Os.FAMILY_WINDOWS)) {
+ commandLine "chmod", "+x", bootWar.archivePath
+ }
+ logger.info "Running ${bootWar.archivePath}"
+ commandLine bootWar.archivePath
+ }
+}
+
+task debug(group: "CAS", description: "Debug the CAS web application in embedded mode on port 5005") {
+ dependsOn 'build'
+ doLast {
+ logger.info "Debugging process is started in a suspended state, listening on port 5005."
+ def casArgs = Arrays.asList("-Xmx2048M".split(" "))
+ javaexec {
+ main = "-jar"
+ jvmArgs = casArgs
+ debug = true
+ args = ["build/libs/${casWebApplicationBinaryName}"]
+ systemProperties = System.properties
+ logger.info "Started ${commandLine}"
+ }
+ }
+}
+
+task downloadShell(group: "Shell", description: "Download CAS shell jar from snapshot or release maven repo") {
+ doFirst {
+ mkdir "${project.shellDir}"
+ }
+ doLast {
+ def downloadFile
+ if (isRunningCasServerSnapshot(casServerVersion)) {
+ def snapshotDir = "https://oss.sonatype.org/content/repositories/snapshots/org/apereo/cas/cas-server-support-shell/${casServerVersion}/"
+ def files = new ApacheURLLister().listFiles(new URL(snapshotDir))
+ files = files.sort { it.path }
+ files.each {
+ if (it.path.endsWith(".jar")) {
+ downloadFile = it
+ }
+ }
+ } else {
+ downloadFile = "https://repo1.maven.org/maven2/org/apereo/cas/cas-server-support-shell/${casServerVersion}/cas-server-support-shell-${casServerVersion}.jar"
+ }
+ logger.info "Downloading file: ${downloadFile}"
+ download {
+ src downloadFile
+ dest new File("${project.shellDir}", "cas-server-support-shell-${casServerVersion}.jar")
+ overwrite false
+ }
+ }
+}
+
+task runShell(group: "Shell", description: "Run the CAS shell") {
+ dependsOn downloadShell
+ doLast {
+ println "Run the following command to launch the shell:\n\tjava -jar ${project.shellDir}/cas-server-support-shell-${casServerVersion}.jar"
+ }
+}
+
+task debugShell(group: "Shell", description: "Run the CAS shell with debug options, wait for debugger on port 5005") {
+ dependsOn downloadShell
+ doLast {
+ println """
+ Run the following command to launch the shell:\n\t
+ java -Xrunjdwp:transport=dt_socket,address=5000,server=y,suspend=y -jar ${project.shellDir}/cas-server-support-shell-${casServerVersion}.jar
+ """
+ }
+}
+
+task showConfiguration(group: "CAS", description: "Show configurations for each dependency, etc") {
+ doLast() {
+ def cfg = project.hasProperty("configuration") ? project.property("configuration") : "compile"
+ configurations.getByName(cfg).each { println it }
+ }
+}
+
+task allDependenciesInsight(group: "build", type: DependencyInsightReportTask, description: "Produce insight information for all dependencies") {}
+
+task allDependencies(group: "build", type: DependencyReportTask, description: "Display a graph of all project dependencies") {}
+
+task casVersion(group: "CAS", description: "Display the current CAS version") {
+ doFirst {
+ def verbose = project.hasProperty("verbose") && Boolean.valueOf(project.getProperty("verbose"))
+ if (verbose) {
+ def out = services.get(StyledTextOutputFactory).create("CAS")
+ println "******************************************************************"
+ out.withStyle(Style.Info).println "Apereo CAS $casServerVersion"
+ out.withStyle(Style.Description).println "Enterprise Single SignOn for all earthlings and beyond"
+ out.withStyle(Style.SuccessHeader).println "- GitHub: "
+ out.withStyle(Style.Success).println "https://github.com/apereo/cas"
+ out.withStyle(Style.SuccessHeader).println "- Docs: "
+ out.withStyle(Style.Success).println "https://apereo.github.io/cas"
+ out.withStyle(Style.SuccessHeader).println "- Blog: "
+ out.withStyle(Style.Success).println "https://apereo.github.io"
+ println "******************************************************************"
+ } else {
+ println casServerVersion
+ }
+ }
+}
+
+task createKeystore(group: "CAS", description: "Create CAS keystore") {
+ doFirst {
+ mkdir "/etc/cas"
+
+ def keystorePath = "/etc/cas/thekeystore"
+
+ def dn = "CN=cas.example.org,OU=Example,OU=Org,C=US"
+ if (project.hasProperty("certificateDn")) {
+ dn = project.getProperty("certificateDn")
+ }
+ def subjectAltName = "dns:example.org,dns:localhost,ip:127.0.0.1"
+ if (project.hasProperty("certificateSubAltName")) {
+ subjectAltName = project.getProperty("certificateSubAltName")
+ }
+ // this will fail if thekeystore exists and has cert with cas alias already (so delete if you want to recreate)
+ logger.info "Generating keystore for CAS with DN ${dn}"
+ exec {
+ workingDir "."
+ commandLine "keytool", "-genkeypair", "-alias", "cas",
+ "-keyalg", "RSA",
+ "-keypass", "changeit", "-storepass", "changeit",
+ "-keystore", keystorePath,
+ "-dname", dn, "-ext", "SAN=${subjectAltName}"
+ }
+ logger.info "Exporting cert from keystore..."
+ exec {
+ workingDir "."
+ commandLine "keytool", "-exportcert", "-alias", "cas",
+ "-storepass", "changeit", "-keystore", keystorePath,
+ "-file", "/etc/cas/cas.cer"
+ }
+ logger.info "Import /etc/cas/cas.cer into your Java truststore (JAVA_HOME/lib/security/cacerts)"
+ }
+}
+
+task listTemplateViews(group: "CAS", description: "List all CAS views") {
+ dependsOn explodeWar
+
+ doFirst {
+ fileTree(explodedResourcesDir).matching {
+ include "**/*.html"
+ }
+ .collect {
+ return it.path.replace(explodedResourcesDir, "")
+ }
+ .toSorted()
+ .each { println it }
+ }
+}
+
+task exportConfigMetadata(group: "CAS", description: "Export collection of CAS properties") {
+ doLast {
+ def file = new File(project.rootDir, 'config-metadata.properties')
+ file.withWriter('utf-8') { writer ->
+ def metadataRepository = new org.apereo.cas.metadata.CasConfigurationMetadataRepository()
+ def repository = metadataRepository.repository;
+ repository.allGroups
+ .values()
+ .sort { o1, o2 -> o1.id <=> o2.id }
+ .each({ group ->
+ def groupProperties = group.properties
+ if (!groupProperties.isEmpty()) {
+ def groupId = group.id.equalsIgnoreCase("_ROOT_GROUP_") ? "" : group.id + "."
+
+ writer.writeLine("# Group ${group.id}");
+ writer.writeLine("# ====================")
+ groupProperties
+ .values()
+ .sort { o1, o2 -> o1.id <=> o2.id }
+ .each({ property ->
+ def description = property.shortDescription
+ if (!property.shortDescription?.equalsIgnoreCase(property.description) && property.description != null) {
+ description = property.description.replace('\n', '#')
+ }
+ writer.writeLine("# ${description}");
+ writer.writeLine("# Type: ${property.type}");
+ if (property.deprecated) {
+ def deprecation = property.deprecation
+ writer.writeLine("# This setting is deprecated with a severity level of ${deprecation.level}.")
+ if (deprecation.shortReason != null) {
+ writer.writeLine("# because ${deprecation.shortReason}")
+ }
+ if (deprecation.replacement != null) {
+ writer.writeLine("# Replace with: ${deprecation.replacement}")
+ }
+ }
+ property.hints.valueHints.each {
+ if (it.value instanceof Object[]) {
+ if (it.value[0].toString().contains("RequiresModule")) {
+ writer.writeLine("# Required module: org.apereo.cas:${it.description}")
+ writer.writeLine("# Automatically included/available: ${it.value[1]}")
+ }
+ }
+ if (it.value.toString().contains("RequiredProperty")) {
+ writer.writeLine("# Note: This setting is required!")
+ }
+ }
+ writer.writeLine("${groupId}${property.name}=${property.defaultValue}")
+ writer.writeLine("")
+ });
+ }
+ });
+ }
+ println "Configuration metadata is available at ${file.absolutePath}"
+ }
+}
+
+task getResource(group: "CAS", description: "Fetch a CAS resource and move it into the overlay") {
+ dependsOn explodeWar
+
+ doFirst {
+ def resourceName = project.getProperty("resourceName")
+
+ def results = fileTree(explodedResourcesDir).matching {
+ include "**/${resourceName}.*"
+ include "**/${resourceName}"
+ }
+ if (results.isEmpty()) {
+ println "No resources could be found matching ${resourceName}"
+ return
+ }
+ if (results.size() > 1) {
+ println "Multiple resources found matching ${resourceName}:\n"
+ results.each {
+ println "\t-" + it.path.replace(explodedResourcesDir, "")
+ }
+ println "\nNarrow down your search criteria and try again."
+ return
+ }
+
+ def fromFile = explodedResourcesDir
+ def resourcesDir = "src/main/resources"
+ mkdir resourcesDir
+
+ def resourceFile = results[0].canonicalPath
+ def toResourceFile = resourceFile.replace(fromFile, resourcesDir)
+
+ def parent = file(toResourceFile).getParent()
+ mkdir parent
+
+ Files.copy(Paths.get(resourceFile), Paths.get(toResourceFile), StandardCopyOption.REPLACE_EXISTING)
+ println "Copied file ${resourceFile} to ${toResourceFile}"
+ }
+}
+
+def isRunningCasServerSnapshot(casServerVersion) {
+ return "${casServerVersion}".contains("-SNAPSHOT")
+}
+
+task verifyRequiredJavaVersion {
+ logger.info "Checking current Java version ${JavaVersion.current()} for required Java version ${project.targetCompatibility}"
+ if (!JavaVersion.current().name.equalsIgnoreCase("${project.targetCompatibility}")) {
+ throw new GradleException("Current Java version ${JavaVersion.current()} does not match required Java version ${project.targetCompatibility}")
+ }
+}
diff --git a/third_party/apereo-cas/overlay/gradle/wrapper/gradle-wrapper.jar b/third_party/apereo-cas/overlay/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 000000000..62d4c0535
Binary files /dev/null and b/third_party/apereo-cas/overlay/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/third_party/apereo-cas/overlay/gradle/wrapper/gradle-wrapper.properties b/third_party/apereo-cas/overlay/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 000000000..4c5803d13
--- /dev/null
+++ b/third_party/apereo-cas/overlay/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.4-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/third_party/apereo-cas/overlay/gradlew b/third_party/apereo-cas/overlay/gradlew
new file mode 100755
index 000000000..fbd7c5158
--- /dev/null
+++ b/third_party/apereo-cas/overlay/gradlew
@@ -0,0 +1,185 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=`expr $i + 1`
+ done
+ case $i in
+ 0) set -- ;;
+ 1) set -- "$args0" ;;
+ 2) set -- "$args0" "$args1" ;;
+ 3) set -- "$args0" "$args1" "$args2" ;;
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=`save "$@"`
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+exec "$JAVACMD" "$@"
diff --git a/third_party/apereo-cas/overlay/gradlew.bat b/third_party/apereo-cas/overlay/gradlew.bat
new file mode 100644
index 000000000..5093609d5
--- /dev/null
+++ b/third_party/apereo-cas/overlay/gradlew.bat
@@ -0,0 +1,104 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/third_party/apereo-cas/overlay/lombok.config b/third_party/apereo-cas/overlay/lombok.config
new file mode 100644
index 000000000..6aa51d71e
--- /dev/null
+++ b/third_party/apereo-cas/overlay/lombok.config
@@ -0,0 +1,2 @@
+# This file is generated by the 'io.freefair.lombok' Gradle plugin
+config.stopBubbling = true
diff --git a/third_party/apereo-cas/overlay/settings.gradle b/third_party/apereo-cas/overlay/settings.gradle
new file mode 100644
index 000000000..3ad50900e
--- /dev/null
+++ b/third_party/apereo-cas/overlay/settings.gradle
@@ -0,0 +1 @@
+rootProject.name='cas'
\ No newline at end of file
diff --git a/third_party/apereo-cas/overlay/src/main/jib/docker/entrypoint.sh b/third_party/apereo-cas/overlay/src/main/jib/docker/entrypoint.sh
new file mode 100755
index 000000000..a3a0895b0
--- /dev/null
+++ b/third_party/apereo-cas/overlay/src/main/jib/docker/entrypoint.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+#echo -e "\nChecking java..."
+#java -version
+
+#echo -e "\nCreating CAS configuration directories..."
+mkdir -p /etc/cas/config
+mkdir -p /etc/cas/services
+
+#echo "Listing provided CAS docker artifacts..."
+#ls -R docker/cas
+
+#echo -e "\nMoving CAS configuration artifacts..."
+mv docker/cas/thekeystore /etc/cas 2>/dev/null
+mv docker/cas/config/*.* /etc/cas/config 2>/dev/null
+mv docker/cas/services/*.* /etc/cas/services 2>/dev/null
+
+#echo -e "\nListing CAS configuration under /etc/cas..."
+#ls -R /etc/cas
+
+echo -e "\nRunning CAS..."
+exec java -Xms512m -Xmx2048M -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -jar docker/cas/war/cas.war
diff --git a/third_party/apereo-cas/overlay/src/main/webapp/WEB-INF/web.xml b/third_party/apereo-cas/overlay/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 000000000..072a6a0fd
--- /dev/null
+++ b/third_party/apereo-cas/overlay/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,7 @@
+
+
+
\ No newline at end of file