diff --git a/test-compose/idp/Dockerfile b/test-compose/idp/Dockerfile index c5f74ab..23686e2 100644 --- a/test-compose/idp/Dockerfile +++ b/test-compose/idp/Dockerfile @@ -17,7 +17,7 @@ ADD ${TOMCERT} /opt/certs ADD ${TOMWWWROOT} /usr/local/tomcat/webapps/ROOT ADD ${SHBCFG} /opt/shibboleth-idp/conf ADD ${SHBCREDS} /opt/shibboleth-idp/credentials -#ADD ${SHBVIEWS} /opt/shibboleth-idp/views +ADD ${SHBVIEWS} /opt/shibboleth-idp/views #ADD ${SHBEDWAPP} /opt/shibboleth-idp/edit-webapp #ADD ${SHBMSGS} /opt/shibboleth-idp/messages ADD ${SHBMD} /opt/shibboleth-idp/metadata diff --git a/test-compose/idp/container_files/config/shib-idp/views/admin/hello.vm b/test-compose/idp/container_files/config/shib-idp/views/admin/hello.vm new file mode 100644 index 0000000..33a0528 --- /dev/null +++ b/test-compose/idp/container_files/config/shib-idp/views/admin/hello.vm @@ -0,0 +1,73 @@ +## +## Velocity Template for Hello World page. +## +## Velocity context will contain the following properties +## flowRequestContext - the Spring Web Flow RequestContext +## encoder - HTMLEncoder class +## request - HttpServletRequest +## response - HttpServletResponse +## profileRequestContext - root of context tree +## subjectContext - ProfileRequestContext -> SubjectContext +## attributeContext - ProfileRequestContext -> AttributeContext +## environment - Spring Environment object for property resolution +## custom - arbitrary object injected by deployer +## + + + + + + #springMessageText("idp.title", "Web Login Service") - #springMessageText("hello-world.title", "Hello World") + + + + +
+
+
+ #springMessageText( +

#springMessageText("idp.title", "Web Login Service")

+
+ +
+

#springMessageText("hello-world.greeting", "Greetings"), $encoder.encodeForHTML($subjectContext.getPrincipalName())

+
+

Authenticated By

+ #foreach ($result in $subjectContext.getAuthenticationResults().entrySet()) +
$encoder.encodeForHTML($result.getKey())
+ #end +
+

Java Principals in Subjects

+ #foreach ($s in $subjectContext.getSubjects()) + #foreach ($p in $s.getPrincipals()) +
$encoder.encodeForHTML($p)
+ #end + #end + #if ($attributeContext && !$attributeContext.getUnfilteredIdPAttributes().isEmpty()) +
+

Attributes:

+ #foreach ($a in $attributeContext.getUnfilteredIdPAttributes()) + #if (!$a.getValues().isEmpty()) +
+
$encoder.encodeForHTML($a.getId())
+ #foreach ($v in $a.getValues()) +
$encoder.encodeForHTML($v.getDisplayValue())
+ #end + #end + #end + #end +
+ +
+

#springMessageText("hello-world.reload", "Reload the Page")

+
+
+ + +
+ + diff --git a/test-compose/idp/container_files/config/shib-idp/views/client-storage/client-storage-read.vm b/test-compose/idp/container_files/config/shib-idp/views/client-storage/client-storage-read.vm new file mode 100644 index 0000000..1993c14 --- /dev/null +++ b/test-compose/idp/container_files/config/shib-idp/views/client-storage/client-storage-read.vm @@ -0,0 +1,53 @@ +## +## Velocity template to read from local storage. +## +## Velocity context will contain the following properties +## flowExecutionUrl - the form action location +## flowRequestContext - the Spring Web Flow RequestContext +## flowExecutionKey - the SWF execution key (this is built into the flowExecutionUrl) +## profileRequestContext - root of context tree +## loadContext - context with details about the storage keys to load +## encoder - HTMLEncoder class +## request - HttpServletRequest +## response - HttpServletResponse +## environment - Spring Environment object for property resolution +#set ($title = $springMacroRequestContext.getMessage("idp.title", "Web Login Service")) +#set ($titleSuffix = $springMacroRequestContext.getMessage("idp.client-storage-read.suffix", "Loading Session Information")) +## + + + + + + $title - $titleSuffix + + + + +
+
+
+

$title - $titleSuffix

+
+
+ $springMacroRequestContext.getMessage("idp.client-storage-read.text", "Loading login session information from the browser...") +
+ + #parse( "client-storage/read.vm" ) +
+ +
+ + diff --git a/test-compose/idp/container_files/config/shib-idp/views/client-storage/client-storage-write.vm b/test-compose/idp/container_files/config/shib-idp/views/client-storage/client-storage-write.vm new file mode 100644 index 0000000..4b92d6b --- /dev/null +++ b/test-compose/idp/container_files/config/shib-idp/views/client-storage/client-storage-write.vm @@ -0,0 +1,53 @@ +## +## Velocity template to write to local storage. +## +## Velocity context will contain the following properties +## flowExecutionUrl - the form action location +## flowRequestContext - the Spring Web Flow RequestContext +## flowExecutionKey - the SWF execution key (this is built into the flowExecutionUrl) +## profileRequestContext - root of context tree +## saveContext - context with details about the storage data to save +## encoder - HTMLEncoder class +## request - HttpServletRequest +## response - HttpServletResponse +## environment - Spring Environment object for property resolution +#set ($title = $springMacroRequestContext.getMessage("idp.title", "Web Login Service")) +#set ($titleSuffix = $springMacroRequestContext.getMessage("idp.client-storage-write.suffix", "Saving Session Information...")) +## + + + + + + $title - $titleSuffix + + + + +
+
+
+

$title - $titleSuffix

+
+
+ $springMacroRequestContext.getMessage("idp.client-storage-write.text", "Saving login session information to the browser...") +
+ + #parse( "client-storage/write.vm" ) +
+ +
+ + \ No newline at end of file diff --git a/test-compose/idp/container_files/config/shib-idp/views/error.vm b/test-compose/idp/container_files/config/shib-idp/views/error.vm new file mode 100644 index 0000000..a44bd6f --- /dev/null +++ b/test-compose/idp/container_files/config/shib-idp/views/error.vm @@ -0,0 +1,75 @@ +## +## Velocity Template for error end-state +## +## Velocity context will contain the following properties +## flowRequestContext - the Spring Web Flow RequestContext +## profileRequestContext - root of context tree +## encoder - HTMLEncoder class +## request - HttpServletRequest +## response - HttpServletResponse +## environment - Spring Environment object for property resolution +## custom - arbitrary object injected by deployer +## +#set ($title = $springMacroRequestContext.getMessage("idp.title", "Web Login Service")) +#set ($defaultTitleSuffix = $springMacroRequestContext.getMessage("idp.title.suffix", "Error")) +## +#if ($flowRequestContext) + ## This handles flow events, the most common case. + #set ($eventId = $flowRequestContext.getCurrentEvent().getId()) + #set ($eventKey = $springMacroRequestContext.getMessage("$eventId", "error")) + #set ($titleSuffix = $springMacroRequestContext.getMessage("${eventKey}.title", "$defaultTitleSuffix")) + #set ($message = $springMacroRequestContext.getMessage("${eventKey}.message", "$defaultTitleSuffix: $eventId")) + #if ($eventId == "AccessDenied" or $eventId == "ContextCheckDenied") + $response.setStatus(403) + #elseif ($eventId == "AttributeReleaseRejected" || $eventId == "TermsRejected") + $response.setStatus(200) + #elseif ($eventKey == "unexpected" || $eventKey == "runtime-error" || $eventKey == "error") + $response.setStatus(500) + #else + $response.setStatus(400) + #end +#elseif ($exception) + ## This handles exceptions that reach the Spring-MVC exception handler. + #set ($eventId = $exception.getClass().getSimpleName()) + #set ($eventKey = $springMacroRequestContext.getMessage("$eventId", "error")) + #set ($titleSuffix = $springMacroRequestContext.getMessage("${eventKey}.title", "$defaultTitleSuffix")) + #set ($message = $springMacroRequestContext.getMessage("${eventKey}.message", "$defaultTitleSuffix: $eventId")) + $response.setStatus(500) +#else + ## This is a catch-all that theoretically shouldn't happen? + #set ($titleSuffix = $defaultTitleSuffix) + #set ($message = $springMacroRequestContext.getMessage("idp.message", "An unidentified error occurred.")) + $response.setStatus(500) +#end +## + + + + + + $title - $titleSuffix + + + + +
+
+
+ #springMessageText( +

$title - $titleSuffix

+
+ +
+ #evaluate($message) +
+
+ + + +
+ + \ No newline at end of file diff --git a/test-compose/idp/container_files/config/shib-idp/views/login-error.vm b/test-compose/idp/container_files/config/shib-idp/views/login-error.vm new file mode 100644 index 0000000..224976b --- /dev/null +++ b/test-compose/idp/container_files/config/shib-idp/views/login-error.vm @@ -0,0 +1,26 @@ +## Velocity Template for login error message production, included by login.vm +## +## authenticationErrorContext - context containing error data, if available +## +#if ($authenticationErrorContext && $authenticationErrorContext.getClassifiedErrors().size() > 0) + ## This handles errors that are classified by the message maps in the authentication config. + #set ($eventId = $authenticationErrorContext.getClassifiedErrors().iterator().next()) + #if ($eventId != "ReselectFlow") + #set ($eventKey = $springMacroRequestContext.getMessage("$eventId", "login")) + #set ($message = $springMacroRequestContext.getMessage("${eventKey}.message", "Login Failure: $eventId")) + #end +#elseif ($authenticationErrorContext && $authenticationErrorContext.getExceptions().size() > 0) + ## This handles login exceptions that are left unclassified. + #set ($loginException = $authenticationErrorContext.getExceptions().get(0)) + #if ($loginException.getMessage()) + #set ($message = "Login Failure: $loginException.getMessage()") + #else + #set ($message = $loginException.toString()) + #end +#end + +#if ($message) +
+

$encoder.encodeForHTML($message)

+
+#end diff --git a/test-compose/idp/container_files/config/shib-idp/views/login.vm b/test-compose/idp/container_files/config/shib-idp/views/login.vm new file mode 100644 index 0000000..c7b15c9 --- /dev/null +++ b/test-compose/idp/container_files/config/shib-idp/views/login.vm @@ -0,0 +1,144 @@ +## +## Velocity Template for DisplayUsernamePasswordPage view-state +## +## Velocity context will contain the following properties +## flowExecutionUrl - the form action location +## flowRequestContext - the Spring Web Flow RequestContext +## flowExecutionKey - the SWF execution key (this is built into the flowExecutionUrl) +## profileRequestContext - root of context tree +## authenticationContext - context with authentication request information +## authenticationErrorContext - context with login error state +## authenticationWarningContext - context with login warning state +## ldapResponseContext - context with LDAP state (if using native LDAP) +## rpUIContext - the context with SP UI information from the metadata +## extendedAuthenticationFlows - collection of "extended" AuthenticationFlowDescriptor objects +## passwordPrincipals - contents of the shibboleth.authn.Password.PrincipalOverride bean +## encoder - HTMLEncoder class +## request - HttpServletRequest +## response - HttpServletResponse +## environment - Spring Environment object for property resolution +## custom - arbitrary object injected by deployer +## +#set ($rpContext = $profileRequestContext.getSubcontext('net.shibboleth.idp.profile.context.RelyingPartyContext')) +#set ($username = $authenticationContext.getSubcontext('net.shibboleth.idp.authn.context.UsernamePasswordContext', true).getUsername()) +#set ($passwordEnabled = false) +#if (!$passwordPrincipals or $passwordPrincipals.isEmpty() or $authenticationContext.isAcceptable($passwordPrincipals)) + #set ($passwordEnabled = true) +#end +## + + + + + + #springMessageText("idp.title", "Web Login Service") + + + +
+
+
+ #springMessageText( +
+ +
+
+ #parse("login-error.vm") + +
+ #parse("csrf/csrf.vm") + #set ($serviceName = $rpUIContext.serviceName) + #if ($serviceName && !$rpContext.getRelyingPartyId().contains($serviceName)) + + #springMessageText("idp.login.loginTo", "Login to") $encoder.encodeForHTML($serviceName) + + #end + + #if ($passwordEnabled) +
+ + +
+ +
+ + +
+ + ## You may need to modify this to taste, such as changing the flow name its checking for to authn/MFA. + #if (!$authenticationContext.getActiveResults().containsKey('authn/Password')) +
+ + +
+ #end + + #end + +
+ + +
+ + #if ($passwordEnabled) +
+ +
+ #end + + #foreach ($extFlow in $extendedAuthenticationFlows) + #if ($authenticationContext.isAcceptable($extFlow) and $extFlow.test(profileRequestContext)) +
+ +
+ #end + #end +
+ + #* + // + // SP Description & Logo (optional) + // These idpui lines will display added information (if available + // in the metadata) about the Service Provider (SP) that requested + // authentication. These idpui lines are "active" in this example + // (not commented out) - this extra SP info will be displayed. + // Remove or comment out these lines to stop the display of the + // added SP information. + // + *# + #set ($logo = $rpUIContext.getLogo()) + #if ($logo) + $encoder.encodeForHTMLAttribute($serviceName) + #end + #set ($desc = $rpUIContext.getServiceDescription()) + #if ($desc) + $encoder.encodeForHTML($desc) + #end + +
+ +
+
+ + +
+ + + \ No newline at end of file diff --git a/test-compose/idp/container_files/config/shib-idp/views/logout-complete.vm b/test-compose/idp/container_files/config/shib-idp/views/logout-complete.vm new file mode 100644 index 0000000..7341e69 --- /dev/null +++ b/test-compose/idp/container_files/config/shib-idp/views/logout-complete.vm @@ -0,0 +1,67 @@ +## +## Velocity Template for logout flow's concluding view-state (no propagation) +## +## Velocity context will contain the following properties +## flowExecutionUrl - the form action location +## flowRequestContext - the Spring Web Flow RequestContext +## flowExecutionKey - the SWF execution key (this is built into the flowExecutionUrl) +## profileRequestContext - root of context tree +## logoutContext - context with SPSession details for logout operation +## multiRPContext - context with RelyingPartyContexts and possibly SP UI information from the metadata +## encoder - HTMLEncoder class +## request - HttpServletRequest +## response - HttpServletResponse +## environment - Spring Environment object for property resolution +## custom - arbitrary object injected by deployer +## +#set ($activeIdPSessions = $logoutContext and !$logoutContext.getIdPSessions().isEmpty()) +#set ($activeSPSessions = $logoutContext and !$logoutContext.getSessionMap().isEmpty()) + + + + + + #springMessageText("idp.title", "Web Login Service") + + + + +
+
+
+ #springMessageText( +
+ +
+
+ #if ($activeIdPSessions) +

#springMessageText("idp.logout.cancelled", "Logout has been cancelled.")

+ #elseif ($activeSPSessions) +

#springMessageText("idp.logout.local", "You elected not to log out of all the applications accessed during your session.")

+ #else +

#springMessageText("idp.logout.complete", "The logout operation is complete, and no other services appear to have been accessed during this session.")

+ #end +
+ +
+
+ + + #if ( $profileRequestContext.getProfileId().contains("saml2/logout") ) + + #end + + +
+ + + \ No newline at end of file diff --git a/test-compose/idp/container_files/config/shib-idp/views/logout-propagate.vm b/test-compose/idp/container_files/config/shib-idp/views/logout-propagate.vm new file mode 100644 index 0000000..470eff5 --- /dev/null +++ b/test-compose/idp/container_files/config/shib-idp/views/logout-propagate.vm @@ -0,0 +1,58 @@ +## +## Velocity Template for logout flow's concluding view-state (with propagation) +## +## Velocity context will contain the following properties +## flowExecutionUrl - the form action location +## flowRequestContext - the Spring Web Flow RequestContext +## flowExecutionKey - the SWF execution key (this is built into the flowExecutionUrl) +## profileRequestContext - root of context tree +## logoutContext - context with SPSession details for logout operation +## multiRPContext - context with RelyingPartyContexts and possibly SP UI information from the metadata +## htmlEncoder - HTMLEncoder class +## urlEncoder - urlEncoder class +## codecUtil - CodecUtil class +## request - HttpServletRequest +## response - HttpServletResponse +## environment - Spring Environment object for property resolution +## custom - arbitrary object injected by deployer +## + + + + + + #springMessageText("idp.title", "Web Login Service") + + + + + +
+
+
+ #springMessageText( +
+ +
+
+

#springMessageText("idp.logout.attempt", "Attempting to log out of the following services:")

+ #parse("logout/propagate.vm") +
+ +
+
+ + +
+ + + \ No newline at end of file diff --git a/test-compose/idp/container_files/config/shib-idp/views/logout.vm b/test-compose/idp/container_files/config/shib-idp/views/logout.vm new file mode 100644 index 0000000..3d8d50b --- /dev/null +++ b/test-compose/idp/container_files/config/shib-idp/views/logout.vm @@ -0,0 +1,131 @@ +## +## Velocity Template for logout flow's starting view-state +## +## Velocity context will contain the following properties +## flowExecutionUrl - the form action location +## flowRequestContext - the Spring Web Flow RequestContext +## flowExecutionKey - the SWF execution key (this is built into the flowExecutionUrl) +## profileRequestContext - root of context tree +## logoutContext - context with SPSession details for logout operation +## multiRPContext - context with RelyingPartyContexts and possibly SP UI information from the metadata +## encoder - HTMLEncoder class +## request - HttpServletRequest +## response - HttpServletResponse +## environment - Spring Environment object for property resolution +## custom - arbitrary object injected by deployer +## +#set ($rpContext = $profileRequestContext.getSubcontext("net.shibboleth.idp.profile.context.RelyingPartyContext")) +#if ($rpContext) +#set ($rpUIContext = $rpContext.getSubcontext("net.shibboleth.idp.ui.context.RelyingPartyUIContext")) +#end +#set ($promptForIdP = $logoutContext and !$logoutContext.getIdPSessions().isEmpty()) +#set ($promptForSP = $logoutContext and !$logoutContext.getSessionMap().isEmpty()) + + + + + + #if ($promptForSP) + + #elseif ($promptForIdP) + + #end + #springMessageText("idp.title", "Web Login Service") + + + + +
+
+
+ #springMessageText( +
+ +
+
+

This page is displayed when a logout operation at the Identity Provider completes. This page is an example + and should be customized. It is not fully internationalized because the presentation will be a highly localized + decision, and we don't have a good suggestion for a default.

+
+ + #if ($rpContext) +

#springMessageText("idp.logout.sp-initiated", "You have been logged out of the following service:")

+
+ #if ($rpUIContext) + $encoder.encodeForHTML($rpUIContext.getServiceName()) + #else + $encoder.encodeForHTML($rpContext.getRelyingPartyId()) + #end +
+
+ #end + + #if ($promptForIdP or $promptForSP) +

#springMessageText("idp.logout.prompt", "Choose one of the following, or wait a few seconds for the default.")

+
+ +
+ +
+ +

#springMessageText("idp.logout.idponly.caption", "End your SSO session.")

+
+ #end + + #if ($promptForSP) +
+ +

#springMessageText("idp.logout.global.caption", "End your SSO session and attempt logout of services accessed during session.")

+
+

#springMessageText("idp.logout.contactServices", "If instructed, the system will attempt to contact the following services:")

+
    + #foreach ($sp in $logoutContext.getSessionMap().keySet()) + #set ($rpCtx = $multiRPContext.getRelyingPartyContextById($sp)) + #if ($rpCtx) + #set ($rpUIContext = $rpCtx.getSubcontext("net.shibboleth.idp.ui.context.RelyingPartyUIContext")) + #end + #if ($rpUIContext and $rpUIContext.getServiceName()) +
  1. $encoder.encodeForHTML($rpUIContext.getServiceName())
  2. + #else +
  3. $encoder.encodeForHTML($sp)
  4. + #end + #end +
+
+
+ #end + + #if ($promptForIdP) +
+ +

#springMessageText("idp.logout.cancel.caption", "Cancel logout and retain your SSO session.")

+
+ #end + + #if ($promptForIdP or $promptForSP) +
+ #else +

#springMessageText("idp.logout.complete", "The logout operation is complete, and no other services appear to have been accessed during this session.")

+ + + #end + +
+ +
+
+ + +
+ + + \ No newline at end of file diff --git a/test-compose/idp/container_files/config/shib-idp/views/user-prefs.js b/test-compose/idp/container_files/config/shib-idp/views/user-prefs.js new file mode 100644 index 0000000..ab994f9 --- /dev/null +++ b/test-compose/idp/container_files/config/shib-idp/views/user-prefs.js @@ -0,0 +1,45 @@ +"use strict"; + +function createCookie(name, value, seconds) { + var date = new Date(); + date.setTime(date.getTime() + (seconds * 1000)); + var expires = "; expires=" + date.toGMTString(); + + var path = '$environment.getProperty("idp.cookie.path", $request.getContextPath())'; + if (path.length > 0) + path = "; path=" + path; + document.cookie = name + "=" + value + expires + path; +} + +function eraseCookie(name) { + createCookie(name, "", -31536000); +} + +function readCookie(name) { + var nameEQ = name + "="; + var ca = document.cookie.split(';'); + for (var i = 0; i < ca.length; i++) { + var c = ca[i]; + while (c.charAt(0) == ' ') + c = c.substring(1, c.length); + if (c.indexOf(nameEQ) == 0) + return c.substring(nameEQ.length, c.length); + } + return null; +} + +function load(id) { + var checkbox = document.getElementById(id); + if (checkbox != null) { + var spnego = readCookie(checkbox.name); + checkbox.checked = (spnego == "1"); + } +} + +function check(checkbox) { + if (checkbox.checked) { + createCookie(checkbox.name, checkbox.value, $environment.getProperty("idp.cookie.maxAge","31536000")); + } else { + eraseCookie(checkbox.name); + } +} diff --git a/test-compose/idp/container_files/config/shib-idp/views/user-prefs.vm b/test-compose/idp/container_files/config/shib-idp/views/user-prefs.vm new file mode 100644 index 0000000..8de0503 --- /dev/null +++ b/test-compose/idp/container_files/config/shib-idp/views/user-prefs.vm @@ -0,0 +1,60 @@ +## +## Velocity Template for user preferences view +## +## Velocity context will contain the following properties +## request - HttpServletRequest +## response - HttpServletResponse +## environment - Spring Environment object for property resolution +## custom - arbitrary object injected by deployer +## + + + + + + #springMessageText("idp.userprefs.title", "Web Login Service") - #springMessageText("idp.userprefs.title.suffix", "Login Preferences") + + + + +
+
+
+ #springMessageText( +

#springMessageText("idp.title", "Web Login Service") - #springMessageText("idp.userprefs.title.suffix", "Login Preferences")

+

+ #springMessage("idp.userprefs.info") +

+
+ + + + +
+ + +
+ + + diff --git a/tests/clairscan.sh b/tests/clairscan.sh index d63ee58..b418d00 100755 --- a/tests/clairscan.sh +++ b/tests/clairscan.sh @@ -15,12 +15,12 @@ else fi #if needed, ensure whitelist file -if [ ! -s ./centos7-clair-whitelist.yaml ]; then - echo 'downloading whitelist file...' - curl -s -L -o ./centos7-clair-whitelist.yaml https://github.internet2.edu/raw/docker/shib-idp/4.1.2_20210607/tests/centos7-clair-whitelist.yaml -else - echo 'using existing whitelist file...' -fi +#if [ ! -s ./centos7-clair-whitelist.yaml ]; then +# echo 'downloading whitelist file...' +# curl -s -L -o ./centos7-clair-whitelist.yaml https://github.internet2.edu/raw/docker/shib-idp/4.1.2_20210607/tests/centos7-clair-whitelist.yaml +#else +# echo 'using existing whitelist file...' +#fi #ensure DB container echo 'ensuring a fresh clair-db container...' @@ -54,8 +54,8 @@ echo 'sending ip addr' ${clairip} 'to clair-scan server...' #run scan echo 'running scan...' -./clair-scanner -w centos7-clair-whitelist.yaml --ip ${clairip} $1 -#./clair-scanner --ip ${clairip} $1 +#./clair-scanner -w centos7-clair-whitelist.yaml --ip ${clairip} $1 +./clair-scanner --ip ${clairip} $1 retcode=$? #eval results