This is an automated email from the ASF dual-hosted git repository. sbglasius pushed a commit to branch fix/cas-single-signout-and-proxy-receptor in repository https://gitbox.apache.org/repos/asf/grails-core.git
commit efa8e7e16af83a9fd91abbf3b5ae8098c008e084 Author: Søren Berg Glasius <[email protected]> AuthorDate: Thu Aug 20 19:48:01 2026 +0200 fix(cas): address review feedback on README, CI duplication and plugin metadata * README: drop two leftover lines from the previous text that survived the rewrite, and correct "two configurations" now that there are three. * Stop running a CAS configuration twice. The specs defaulted to the 'cas' configuration when TESTCONFIG was unset, so the broad 'security' job ran it in each of its matrix entries on top of the dedicated casSecurityConfig job. They now require a configuration to be selected, matching the core functional-test-app precedent, so 'security' skips them and each configuration runs exactly once. bootRun still needs no TESTCONFIG. * Plugin metadata: the plugin uses org.apereo.cas.client, so call it Apereo rather than Jasig, in the plugin title/description and in the guide, where three dead jasig.org links are repointed at apereo.github.io. Bump grailsVersion and repoint organization, issueManagement and scm at apache/grails-core, matching the convention used elsewhere on this branch. --- .github/workflows/gradle.yml | 9 +++++---- .../en/guide/security/securityPlugins/springSecurity.adoc | 4 ++-- .../securityPlugins/springSecurity/cas/introduction.adoc | 2 +- .../security/securityPlugins/springSecurity/cas/usage.adoc | 2 +- .../cas/SpringSecurityCasGrailsPlugin.groovy | 12 ++++++------ grails-test-examples/spring-security/cas/README.md | 8 +++++--- .../plugin/springsecurity/cas/test/CasLoginSpec.groovy | 3 +++ .../springsecurity/cas/test/CasNoProxyReceptorSpec.groovy | 2 +- .../springsecurity/cas/test/CasNoSingleSignOutSpec.groovy | 2 +- .../springsecurity/cas/test/CasSingleSignOutSpec.groovy | 2 +- .../plugin/springsecurity/cas/test/CasTestConfig.groovy | 14 +++++++++++++- 11 files changed, 39 insertions(+), 21 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 90ae54e7bc..58e3b976da 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -575,10 +575,11 @@ jobs: fail-fast: false matrix: # The CAS test app authenticates against a real Apereo CAS server started via Testcontainers. - # 'cas' leaves the proxy settings unset and is the default, so it is also covered by the main - # security job; 'casProxy' exercises the proxy-granting-ticket callback; 'casNoSingleSignout' - # asserts the shipped default, where single signout is not enabled. - # TESTCONFIG is applied at app startup, so every config must be its own run. + # 'cas' leaves the proxy settings unset; 'casProxy' exercises the proxy-granting-ticket + # callback; 'casNoSingleSignout' asserts the shipped default, where single signout is off. + # TESTCONFIG is applied at app startup, so every config must be its own run. The specs are + # gated on a config being selected, so the broad 'security' job skips them and no config is + # run twice. # Carried over from the standalone grails-spring-security CI convention - add, don't remove. test-config: [ 'cas', 'casProxy', 'casNoSingleSignout' ] runs-on: ubuntu-24.04 diff --git a/grails-doc/src/en/guide/security/securityPlugins/springSecurity.adoc b/grails-doc/src/en/guide/security/securityPlugins/springSecurity.adoc index 4a6c174513..73fea73664 100644 --- a/grails-doc/src/en/guide/security/securityPlugins/springSecurity.adoc +++ b/grails-doc/src/en/guide/security/securityPlugins/springSecurity.adoc @@ -19,13 +19,13 @@ under the License. The Spring Security plugins are built on the https://spring.io/projects/spring-security[Spring Security] project which provides a flexible, extensible framework for building all sorts of authentication and authorization schemes. The plugins are modular so you can install just the functionality that you need for your application. The Spring Security plugins are the official security plugins for Grails and are actively maintained and supported. -The *Core* plugin supports form-based authentication, encrypted/salted passwords, HTTP Basic authentication, etc. and secondary dependent plugins provide alternate functionality such as ACL support, single sign-on with Jasig CAS, LDAP authentication, OAuth2 client support, REST token authentication, and a plugin providing user interface extensions and security workflows. +The *Core* plugin supports form-based authentication, encrypted/salted passwords, HTTP Basic authentication, etc. and secondary dependent plugins provide alternate functionality such as ACL support, single sign-on with Apereo CAS, LDAP authentication, OAuth2 client support, REST token authentication, and a plugin providing user interface extensions and security workflows. The reference documentation for each plugin is included in the following sections: * <<springSecurityCore,Core Plugin>> — the foundational authentication and authorization plugin. * <<springSecurityAcl,ACL Plugin>> — domain-instance-level access control lists. -* <<springSecurityCas,CAS Plugin>> — single sign-on with Apereo (Jasig) CAS. +* <<springSecurityCas,CAS Plugin>> — single sign-on with Apereo CAS. * <<springSecurityLdap,LDAP Plugin>> — authentication against an LDAP server. * <<springSecurityOauth2,OAuth2 Plugin>> — authentication using external OAuth2 providers. * <<springSecurityRest,REST Plugin>> — token-based authentication for stateless REST APIs. diff --git a/grails-doc/src/en/guide/security/securityPlugins/springSecurity/cas/introduction.adoc b/grails-doc/src/en/guide/security/securityPlugins/springSecurity/cas/introduction.adoc index 8ef1e35288..90b4cb0c5e 100644 --- a/grails-doc/src/en/guide/security/securityPlugins/springSecurity/cas/introduction.adoc +++ b/grails-doc/src/en/guide/security/securityPlugins/springSecurity/cas/introduction.adoc @@ -20,6 +20,6 @@ under the License. [[cas-introduction]] == Introduction to the Spring Security CAS Plugin -The CAS plugin adds https://www.jasig.org/cas[CAS] single sign-on support to a Grails application that uses Spring Security. It depends on the xref:springSecurityCore.adoc#springSecurityCore[Spring Security Core plugin]. +The CAS plugin adds https://apereo.github.io/cas[CAS] single sign-on support to a Grails application that uses Spring Security. It depends on the xref:springSecurityCore.adoc#springSecurityCore[Spring Security Core plugin]. Once you have configured a CAS server and have configured your Grails application(s) as clients, you can authenticate to any application that is a client of the CAS server and be automatically authenticated to all other clients. \ No newline at end of file diff --git a/grails-doc/src/en/guide/security/securityPlugins/springSecurity/cas/usage.adoc b/grails-doc/src/en/guide/security/securityPlugins/springSecurity/cas/usage.adoc index 5c469761ec..b4990fe56f 100644 --- a/grails-doc/src/en/guide/security/securityPlugins/springSecurity/cas/usage.adoc +++ b/grails-doc/src/en/guide/security/securityPlugins/springSecurity/cas/usage.adoc @@ -25,7 +25,7 @@ under the License. Configuring your CAS server is beyond the scope of this document. There are many different approaches and this will most likely be done by IT staff. It's assumed here that you already have a running CAS server. ==== -https://www.jasig.org/cas[CAS] is a popular single sign-on implementation. It's open source and has an Apache-like license, and is easy to get started with but is also highly configurable. In addition it has clients written in Java, .Net, PHP, Perl, and other languages. +https://apereo.github.io/cas[CAS] is a popular single sign-on implementation. It's open source and has an Apache-like license, and is easy to get started with but is also highly configurable. In addition it has clients written in Java, .Net, PHP, Perl, and other languages. === Installation diff --git a/grails-spring-security/cas/plugin/src/main/groovy/grails/plugin/springsecurity/cas/SpringSecurityCasGrailsPlugin.groovy b/grails-spring-security/cas/plugin/src/main/groovy/grails/plugin/springsecurity/cas/SpringSecurityCasGrailsPlugin.groovy index 06fb2c5dcb..516ab47e8c 100644 --- a/grails-spring-security/cas/plugin/src/main/groovy/grails/plugin/springsecurity/cas/SpringSecurityCasGrailsPlugin.groovy +++ b/grails-spring-security/cas/plugin/src/main/groovy/grails/plugin/springsecurity/cas/SpringSecurityCasGrailsPlugin.groovy @@ -47,17 +47,17 @@ import grails.plugins.Plugin @CompileStatic class SpringSecurityCasGrailsPlugin extends Plugin { - String grailsVersion = '7.0.0 > *' + String grailsVersion = '8.0.0-SNAPSHOT > *' String author = 'Burt Beckwith' String authorEmail = '' - String title = 'Jasig CAS support for the Spring Security plugin.' - String description = 'Jasig CAS support for the Spring Security plugin.' + String title = 'Apereo CAS support for the Spring Security plugin.' + String description = 'Apereo CAS support for the Spring Security plugin.' String documentation = 'https://apache.github.io/grails-spring-security' String license = 'APACHE' List loadAfter = ['springSecurityCore'] - def organization = [name: 'Grails', url: 'https://www.grails.org'] - def issueManagement = [url: 'https://github.com/apache/grails-spring-security/issues'] - def scm = [url: 'https://github.com/apache/grails-spring-security'] + def organization = [name: 'Grails', url: 'https://grails.apache.org/'] + def issueManagement = [system: 'Github', url: 'https://github.com/apache/grails-core/issues'] + def scm = [url: 'https://github.com/apache/grails-core'] def profiles = ['web'] @CompileDynamic diff --git a/grails-test-examples/spring-security/cas/README.md b/grails-test-examples/spring-security/cas/README.md index 324815c1fd..805332ab74 100644 --- a/grails-test-examples/spring-security/cas/README.md +++ b/grails-test-examples/spring-security/cas/README.md @@ -14,8 +14,6 @@ See the License for the specific language governing permissions and limitations under the License. --> -This is a CAS-enabled test application. To run it successfully, a CAS -server is required. The URL for the CAS server is configured in the This is a CAS-enabled test application. It no longer needs a hand-run CAS server: an [Apereo CAS](https://github.com/apereo/cas) server is started in a container by [CasContainerHolder](test1/src/main/groovy/grails/plugin/springsecurity/cas/test/CasContainerHolder.groovy), @@ -25,9 +23,13 @@ container runtime) is therefore required to run or test this application. ## Running the tests -The application is exercised under two configurations, selected with the `TESTCONFIG` system +The application is exercised under three configurations, selected with the `TESTCONFIG` system property. Each has to be its own run, because the configuration is applied at application startup. +The specs only run when one of these is selected, so a build that covers every Spring Security +example does not repeat a configuration that the dedicated per-configuration CI job already runs. +Running `check` without `-DTESTCONFIG` therefore reports no CAS tests. + | `TESTCONFIG` | Configuration | Covered by | |---|---|---| | `cas` (default) | `proxyCallbackUrl` and `proxyReceptorUrl` unset, single signout enabled | `CasLoginSpec`, `CasNoProxyReceptorSpec`, `CasSingleSignOutSpec` | diff --git a/grails-test-examples/spring-security/cas/test1/src/integration-test/groovy/grails/plugin/springsecurity/cas/test/CasLoginSpec.groovy b/grails-test-examples/spring-security/cas/test1/src/integration-test/groovy/grails/plugin/springsecurity/cas/test/CasLoginSpec.groovy index c0375124b4..2d9cd362c4 100644 --- a/grails-test-examples/spring-security/cas/test1/src/integration-test/groovy/grails/plugin/springsecurity/cas/test/CasLoginSpec.groovy +++ b/grails-test-examples/spring-security/cas/test1/src/integration-test/groovy/grails/plugin/springsecurity/cas/test/CasLoginSpec.groovy @@ -20,6 +20,8 @@ package grails.plugin.springsecurity.cas.test +import spock.lang.IgnoreIf + import java.net.http.HttpResponse /** @@ -27,6 +29,7 @@ import java.net.http.HttpResponse * ticket validated against the CAS server, and the resulting authentication carrying the roles * looked up in GORM. */ +@IgnoreIf({ !CasTestConfig.configured }) class CasLoginSpec extends AbstractCasSpec { void 'an unauthenticated request is redirected to the CAS login page for this service'() { diff --git a/grails-test-examples/spring-security/cas/test1/src/integration-test/groovy/grails/plugin/springsecurity/cas/test/CasNoProxyReceptorSpec.groovy b/grails-test-examples/spring-security/cas/test1/src/integration-test/groovy/grails/plugin/springsecurity/cas/test/CasNoProxyReceptorSpec.groovy index f34c5db67e..7b4d1f6654 100644 --- a/grails-test-examples/spring-security/cas/test1/src/integration-test/groovy/grails/plugin/springsecurity/cas/test/CasNoProxyReceptorSpec.groovy +++ b/grails-test-examples/spring-security/cas/test1/src/integration-test/groovy/grails/plugin/springsecurity/cas/test/CasNoProxyReceptorSpec.groovy @@ -35,7 +35,7 @@ import java.net.http.HttpResponse * produced a matcher for the literal path {@code /**null}, which quietly made an unconfigured app * serve a live proxy receptor.</p> */ -@IgnoreIf({ CasTestConfig.proxyEnabled }) +@IgnoreIf({ !CasTestConfig.configured || CasTestConfig.proxyEnabled }) class CasNoProxyReceptorSpec extends AbstractCasSpec { @Autowired diff --git a/grails-test-examples/spring-security/cas/test1/src/integration-test/groovy/grails/plugin/springsecurity/cas/test/CasNoSingleSignOutSpec.groovy b/grails-test-examples/spring-security/cas/test1/src/integration-test/groovy/grails/plugin/springsecurity/cas/test/CasNoSingleSignOutSpec.groovy index c84448d6f5..1721a0103e 100644 --- a/grails-test-examples/spring-security/cas/test1/src/integration-test/groovy/grails/plugin/springsecurity/cas/test/CasNoSingleSignOutSpec.groovy +++ b/grails-test-examples/spring-security/cas/test1/src/integration-test/groovy/grails/plugin/springsecurity/cas/test/CasNoSingleSignOutSpec.groovy @@ -30,7 +30,7 @@ import java.net.http.HttpResponse * something an application should get without asking. With it off, a CAS logout request must not * reach into the application's sessions.</p> */ -@IgnoreIf({ CasTestConfig.singleSignoutEnabled }) +@IgnoreIf({ !CasTestConfig.configured || CasTestConfig.singleSignoutEnabled }) class CasNoSingleSignOutSpec extends AbstractCasSpec { void 'a CAS logout request is ignored when single signout is not enabled'() { diff --git a/grails-test-examples/spring-security/cas/test1/src/integration-test/groovy/grails/plugin/springsecurity/cas/test/CasSingleSignOutSpec.groovy b/grails-test-examples/spring-security/cas/test1/src/integration-test/groovy/grails/plugin/springsecurity/cas/test/CasSingleSignOutSpec.groovy index 3420542d37..4614b3bc27 100644 --- a/grails-test-examples/spring-security/cas/test1/src/integration-test/groovy/grails/plugin/springsecurity/cas/test/CasSingleSignOutSpec.groovy +++ b/grails-test-examples/spring-security/cas/test1/src/integration-test/groovy/grails/plugin/springsecurity/cas/test/CasSingleSignOutSpec.groovy @@ -33,7 +33,7 @@ import java.net.http.HttpResponse * invalidating it - and posting the same message CAS would send exercises exactly that, without * depending on how the CAS server is configured to emit it.</p> */ -@IgnoreIf({ !CasTestConfig.singleSignoutEnabled }) +@IgnoreIf({ !CasTestConfig.configured || !CasTestConfig.singleSignoutEnabled }) class CasSingleSignOutSpec extends AbstractCasSpec { void 'a CAS logout request invalidates the session that the service ticket authenticated'() { diff --git a/grails-test-examples/spring-security/cas/test1/src/main/groovy/grails/plugin/springsecurity/cas/test/CasTestConfig.groovy b/grails-test-examples/spring-security/cas/test1/src/main/groovy/grails/plugin/springsecurity/cas/test/CasTestConfig.groovy index ca177bd684..d874c41c54 100644 --- a/grails-test-examples/spring-security/cas/test1/src/main/groovy/grails/plugin/springsecurity/cas/test/CasTestConfig.groovy +++ b/grails-test-examples/spring-security/cas/test1/src/main/groovy/grails/plugin/springsecurity/cas/test/CasTestConfig.groovy @@ -50,8 +50,20 @@ class CasTestConfig { /** Runs the app without opting in to single signout, to assert the shipped default. */ static final String NO_SINGLE_SIGNOUT_TEST_CONFIG = 'casNoSingleSignout' + static final List<String> TEST_CONFIGS = + [DEFAULT_TEST_CONFIG, PROXY_TEST_CONFIG, NO_SINGLE_SIGNOUT_TEST_CONFIG].asImmutable() + static String getTestConfig() { - System.getProperty('TESTCONFIG') ?: DEFAULT_TEST_CONFIG + System.getProperty('TESTCONFIG') + } + + /** + * Whether a CAS configuration was selected. The specs run only when one was, so that a build + * covering every Spring Security example does not repeat a configuration that the dedicated + * per-configuration job already runs. {@code bootRun} does not need one. + */ + static boolean isConfigured() { + testConfig in TEST_CONFIGS } static boolean isProxyEnabled() {
