From df0ec59ae4e2deef6c2b5d06374ea1e22f63ae69 Mon Sep 17 00:00:00 2001 From: Janne Valkealahti Date: Tue, 28 Mar 2023 08:37:19 +0100 Subject: [PATCH] Migrate client examples - Build both sec-client-rest-template and sec-server-client-auth - Migrate HttpClient 4.x to 5.x - Relates #165 --- settings.gradle | 2 + .../spring-security-kerberos-client.gradle | 1 + .../kerberos/client/KerberosRestTemplate.java | 38 ++++++++-------- .../sec-client-rest-template.gradle | 17 +++++++ .../src/main/java/demo/app/Application.java | 21 +++++++-- .../src/main/resources/application.yml | 4 +- .../sec-server-client-auth.gradle | 22 +++++++++ .../src/main/java/demo/app/Application.java | 19 ++++++-- .../demo/app/DummyUserDetailsService.java | 30 +++++++++++++ .../src/main/java/demo/app/MvcConfig.java | 20 +++++++-- .../main/java/demo/app/WebSecurityConfig.java | 45 +++++++++++-------- .../main/java/demo/app/WebSecurityConfig.java | 26 ++++++----- .../src/main/resources/application.yml | 2 +- 13 files changed, 186 insertions(+), 61 deletions(-) create mode 100644 spring-security-kerberos-samples/sec-client-rest-template/sec-client-rest-template.gradle create mode 100644 spring-security-kerberos-samples/sec-server-client-auth/sec-server-client-auth.gradle create mode 100644 spring-security-kerberos-samples/sec-server-client-auth/src/main/java/demo/app/DummyUserDetailsService.java diff --git a/settings.gradle b/settings.gradle index 29b88a0..8da34c5 100644 --- a/settings.gradle +++ b/settings.gradle @@ -30,6 +30,8 @@ include 'spring-security-kerberos-bom' include 'spring-security-kerberos-core' include 'spring-security-kerberos-client' include 'spring-security-kerberos-web' +include 'spring-security-kerberos-samples:sec-client-rest-template' +include 'spring-security-kerberos-samples:sec-server-client-auth' include 'spring-security-kerberos-samples:sec-server-spnego-form-auth' include 'spring-security-kerberos-docs' diff --git a/spring-security-kerberos-client/spring-security-kerberos-client.gradle b/spring-security-kerberos-client/spring-security-kerberos-client.gradle index 4bc338f..0882cb6 100644 --- a/spring-security-kerberos-client/spring-security-kerberos-client.gradle +++ b/spring-security-kerberos-client/spring-security-kerberos-client.gradle @@ -9,6 +9,7 @@ dependencies { implementation project(':spring-security-kerberos-core') implementation project(':spring-security-kerberos-web') // api('org.apache.httpcomponents:httpclient') + api('org.springframework:spring-web') api('org.apache.httpcomponents.client5:httpclient5') optional 'org.springframework.security:spring-security-ldap' // api('org.springframework.security:spring-security-web') diff --git a/spring-security-kerberos-client/src/main/java/org/springframework/security/kerberos/client/KerberosRestTemplate.java b/spring-security-kerberos-client/src/main/java/org/springframework/security/kerberos/client/KerberosRestTemplate.java index 60049e8..3effafb 100644 --- a/spring-security-kerberos-client/src/main/java/org/springframework/security/kerberos/client/KerberosRestTemplate.java +++ b/spring-security-kerberos-client/src/main/java/org/springframework/security/kerberos/client/KerberosRestTemplate.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 the original author or authors. + * Copyright 2015-2023 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. @@ -36,27 +36,20 @@ import javax.security.auth.login.Configuration; import javax.security.auth.login.LoginContext; import javax.security.auth.login.LoginException; +import org.apache.hc.client5.http.SystemDefaultDnsResolver; import org.apache.hc.client5.http.auth.AuthSchemeFactory; import org.apache.hc.client5.http.auth.AuthScope; import org.apache.hc.client5.http.auth.Credentials; +import org.apache.hc.client5.http.auth.KerberosConfig; +import org.apache.hc.client5.http.auth.StandardAuthScheme; import org.apache.hc.client5.http.classic.HttpClient; import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider; import org.apache.hc.client5.http.impl.auth.SPNegoSchemeFactory; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; import org.apache.hc.core5.http.config.Lookup; +import org.apache.hc.core5.http.config.RegistryBuilder; -// import org.apache.http.auth.AuthSchemeProvider; -// import org.apache.http.auth.AuthScope; -// import org.apache.http.auth.Credentials; -// import org.apache.http.client.HttpClient; -// import org.apache.http.client.config.AuthSchemes; -// import org.apache.http.config.Lookup; -// import org.apache.http.config.RegistryBuilder; -// import org.apache.http.impl.auth.SPNegoSchemeFactory; -// import org.apache.http.impl.client.BasicCredentialsProvider; -// import org.apache.http.impl.client.CloseableHttpClient; -// import org.apache.http.impl.client.HttpClientBuilder; import org.springframework.http.HttpMethod; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.util.StringUtils; @@ -207,9 +200,16 @@ public class KerberosRestTemplate extends RestTemplate { */ private static HttpClient buildHttpClient() { HttpClientBuilder builder = HttpClientBuilder.create(); - // Lookup authSchemeRegistry = RegistryBuilder. create() - // .register(AuthSchemes.SPNEGO, new SPNegoSchemeFactory(true)).build(); - Lookup authSchemeRegistry = null; + + Lookup authSchemeRegistry = RegistryBuilder.create() + .register(StandardAuthScheme.SPNEGO, new SPNegoSchemeFactory( + KerberosConfig.custom() + .setStripPort(KerberosConfig.Option.ENABLE) + .setUseCanonicalHostname(KerberosConfig.Option.DISABLE) + .build(), + SystemDefaultDnsResolver.INSTANCE)) + .build(); + builder.setDefaultAuthSchemeRegistry(authSchemeRegistry); BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider(); credentialsProvider.setCredentials(new AuthScope(null, -1), credentials); @@ -234,7 +234,7 @@ public class KerberosRestTemplate extends RestTemplate { } @Override - protected final T doExecute(final URI url, final HttpMethod method, final RequestCallback requestCallback, + protected final T doExecute(final URI url, final String uriTemplate, final HttpMethod method, final RequestCallback requestCallback, final ResponseExtractor responseExtractor) throws RestClientException { try { @@ -245,7 +245,7 @@ public class KerberosRestTemplate extends RestTemplate { @Override public T run() { - return KerberosRestTemplate.this.doExecuteSubject(url, method, requestCallback, responseExtractor); + return KerberosRestTemplate.this.doExecuteSubject(url, uriTemplate, method, requestCallback, responseExtractor); } }); @@ -254,9 +254,9 @@ public class KerberosRestTemplate extends RestTemplate { } } - private T doExecuteSubject(URI url, HttpMethod method, RequestCallback requestCallback, + private T doExecuteSubject(URI url, String uriTemplate, HttpMethod method, RequestCallback requestCallback, ResponseExtractor responseExtractor) throws RestClientException { - return super.doExecute(url, method, requestCallback, responseExtractor); + return super.doExecute(url, uriTemplate, method, requestCallback, responseExtractor); } private static class ClientLoginConfig extends Configuration { diff --git a/spring-security-kerberos-samples/sec-client-rest-template/sec-client-rest-template.gradle b/spring-security-kerberos-samples/sec-client-rest-template/sec-client-rest-template.gradle new file mode 100644 index 0000000..3235d9f --- /dev/null +++ b/spring-security-kerberos-samples/sec-client-rest-template/sec-client-rest-template.gradle @@ -0,0 +1,17 @@ +plugins { + id 'org.springframework.security.kerberos.sample' + id 'org.springframework.boot' + id 'io.spring.dependency-management' +} + +description = 'Security Client RestTemplate Sample' + +dependencies { + management platform(project(":spring-security-kerberos-management")) + implementation project(':spring-security-kerberos-client') + implementation 'org.springframework.boot:spring-boot-starter' + testImplementation 'org.springframework:spring-test' + testImplementation 'org.junit.jupiter:junit-jupiter' + testImplementation 'org.mockito:mockito-junit-jupiter' + testImplementation 'org.assertj:assertj-core' +} diff --git a/spring-security-kerberos-samples/sec-client-rest-template/src/main/java/demo/app/Application.java b/spring-security-kerberos-samples/sec-client-rest-template/src/main/java/demo/app/Application.java index ea6a4ae..a7300a6 100644 --- a/spring-security-kerberos-samples/sec-client-rest-template/src/main/java/demo/app/Application.java +++ b/spring-security-kerberos-samples/sec-client-rest-template/src/main/java/demo/app/Application.java @@ -1,10 +1,26 @@ +/* + * Copyright 2023 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. + */ package demo.app; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration; +import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.security.kerberos.client.KerberosRestTemplate; @@ -30,7 +46,6 @@ public class Application implements CommandLineRunner { } public static void main(String[] args) throws Throwable { - new SpringApplicationBuilder(Application.class).web(false).run(args); + new SpringApplicationBuilder(Application.class).web(WebApplicationType.NONE).run(args); } - } diff --git a/spring-security-kerberos-samples/sec-client-rest-template/src/main/resources/application.yml b/spring-security-kerberos-samples/sec-client-rest-template/src/main/resources/application.yml index 2394bb4..37c1288 100644 --- a/spring-security-kerberos-samples/sec-client-rest-template/src/main/resources/application.yml +++ b/spring-security-kerberos-samples/sec-client-rest-template/src/main/resources/application.yml @@ -1,4 +1,4 @@ app: - user-principal: user2@EXAMPLE.ORG + user-principal: user2@KERBOS.COM keytab-location: /tmp/user2.keytab - access-url: http://neo.example.org:8080/hello + access-url: http://cypher.localdomain:8080/hello diff --git a/spring-security-kerberos-samples/sec-server-client-auth/sec-server-client-auth.gradle b/spring-security-kerberos-samples/sec-server-client-auth/sec-server-client-auth.gradle new file mode 100644 index 0000000..196226c --- /dev/null +++ b/spring-security-kerberos-samples/sec-server-client-auth/sec-server-client-auth.gradle @@ -0,0 +1,22 @@ +plugins { + id 'org.springframework.security.kerberos.sample' + id 'org.springframework.boot' + id 'io.spring.dependency-management' +} + +description = 'Security Server Client Auth Sample' + +dependencies { + management platform(project(":spring-security-kerberos-management")) + implementation project(':spring-security-kerberos-core') + implementation project(':spring-security-kerberos-web') + implementation 'org.springframework.security:spring-security-config' + implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6' + implementation 'org.springframework.boot:spring-boot-starter' + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' + testImplementation 'org.springframework:spring-test' + testImplementation 'org.junit.jupiter:junit-jupiter' + testImplementation 'org.mockito:mockito-junit-jupiter' + testImplementation 'org.assertj:assertj-core' +} diff --git a/spring-security-kerberos-samples/sec-server-client-auth/src/main/java/demo/app/Application.java b/spring-security-kerberos-samples/sec-server-client-auth/src/main/java/demo/app/Application.java index d2b66db..5ce441b 100644 --- a/spring-security-kerberos-samples/sec-server-client-auth/src/main/java/demo/app/Application.java +++ b/spring-security-kerberos-samples/sec-server-client-auth/src/main/java/demo/app/Application.java @@ -1,16 +1,27 @@ +/* + * Copyright 2023 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. + */ package demo.app; import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration; @SpringBootApplication -@EnableAutoConfiguration(exclude = SecurityAutoConfiguration.class) public class Application { public static void main(String[] args) throws Throwable { SpringApplication.run(Application.class, args); } - } diff --git a/spring-security-kerberos-samples/sec-server-client-auth/src/main/java/demo/app/DummyUserDetailsService.java b/spring-security-kerberos-samples/sec-server-client-auth/src/main/java/demo/app/DummyUserDetailsService.java new file mode 100644 index 0000000..9cb5cec --- /dev/null +++ b/spring-security-kerberos-samples/sec-server-client-auth/src/main/java/demo/app/DummyUserDetailsService.java @@ -0,0 +1,30 @@ +/* + * Copyright 2023 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. + */ +package demo.app; + +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; + +public class DummyUserDetailsService implements UserDetailsService { + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + return new User(username, "{noop}notUsed", true, true, true, true, AuthorityUtils.createAuthorityList("ROLE_USER")); + } +} diff --git a/spring-security-kerberos-samples/sec-server-client-auth/src/main/java/demo/app/MvcConfig.java b/spring-security-kerberos-samples/sec-server-client-auth/src/main/java/demo/app/MvcConfig.java index cb578b3..2f66516 100644 --- a/spring-security-kerberos-samples/sec-server-client-auth/src/main/java/demo/app/MvcConfig.java +++ b/spring-security-kerberos-samples/sec-server-client-auth/src/main/java/demo/app/MvcConfig.java @@ -1,11 +1,26 @@ +/* + * Copyright 2023 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. + */ package demo.app; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration -public class MvcConfig extends WebMvcConfigurerAdapter { +public class MvcConfig implements WebMvcConfigurer { @Override public void addViewControllers(ViewControllerRegistry registry) { @@ -14,5 +29,4 @@ public class MvcConfig extends WebMvcConfigurerAdapter { registry.addViewController("/hello").setViewName("hello"); registry.addViewController("/login").setViewName("login"); } - } diff --git a/spring-security-kerberos-samples/sec-server-client-auth/src/main/java/demo/app/WebSecurityConfig.java b/spring-security-kerberos-samples/sec-server-client-auth/src/main/java/demo/app/WebSecurityConfig.java index 2c3e209..ff6aa35 100644 --- a/spring-security-kerberos-samples/sec-server-client-auth/src/main/java/demo/app/WebSecurityConfig.java +++ b/spring-security-kerberos-samples/sec-server-client-auth/src/main/java/demo/app/WebSecurityConfig.java @@ -1,38 +1,47 @@ +/* + * Copyright 2023 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. + */ package demo.app; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.kerberos.authentication.KerberosAuthenticationProvider; import org.springframework.security.kerberos.authentication.sun.SunJaasKerberosClient; - -import demo.DummyUserDetailsService; +import org.springframework.security.web.SecurityFilterChain; @Configuration -@EnableWebMvcSecurity -public class WebSecurityConfig extends WebSecurityConfigurerAdapter { +@EnableWebSecurity +public class WebSecurityConfig { - @Override - protected void configure(HttpSecurity http) throws Exception { + @Bean + public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http - .authorizeRequests() - .antMatchers("/", "/home").permitAll() + .authorizeHttpRequests((authz) -> authz + .requestMatchers("/", "/home").permitAll() .anyRequest().authenticated() - .and() + ) .formLogin() .loginPage("/login").permitAll() .and() .logout() - .permitAll(); - } - - @Override - protected void configure(AuthenticationManagerBuilder auth) throws Exception { - auth + .permitAll() + .and() .authenticationProvider(kerberosAuthenticationProvider()); + return http.build(); } @Bean diff --git a/spring-security-kerberos-samples/sec-server-spnego-form-auth/src/main/java/demo/app/WebSecurityConfig.java b/spring-security-kerberos-samples/sec-server-spnego-form-auth/src/main/java/demo/app/WebSecurityConfig.java index fa559a5..be4dd7a 100644 --- a/spring-security-kerberos-samples/sec-server-spnego-form-auth/src/main/java/demo/app/WebSecurityConfig.java +++ b/spring-security-kerberos-samples/sec-server-spnego-form-auth/src/main/java/demo/app/WebSecurityConfig.java @@ -20,6 +20,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.FileSystemResource; import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.ProviderManager; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.kerberos.authentication.KerberosAuthenticationProvider; @@ -42,13 +43,17 @@ public class WebSecurityConfig { private String keytabLocation; @Bean - public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - AuthenticationManager authenticationManager = http.getSharedObject(AuthenticationManager.class); - http - .authorizeHttpRequests((authz) -> authz + public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + KerberosAuthenticationProvider kerberosAuthenticationProvider = kerberosAuthenticationProvider(); + KerberosServiceAuthenticationProvider kerberosServiceAuthenticationProvider = kerberosServiceAuthenticationProvider(); + ProviderManager providerManager = new ProviderManager(kerberosAuthenticationProvider, + kerberosServiceAuthenticationProvider); + + http + .authorizeHttpRequests((authz) -> authz .requestMatchers("/", "/home").permitAll() - .anyRequest().authenticated() - ) + .anyRequest().authenticated() + ) .exceptionHandling() .authenticationEntryPoint(spnegoEntryPoint()) .and() @@ -60,11 +65,10 @@ public class WebSecurityConfig { .and() .authenticationProvider(kerberosAuthenticationProvider()) .authenticationProvider(kerberosServiceAuthenticationProvider()) - .addFilterBefore(spnegoAuthenticationProcessingFilter(authenticationManager), - BasicAuthenticationFilter.class) - ; - return http.build(); - } + .addFilterBefore(spnegoAuthenticationProcessingFilter(providerManager), + BasicAuthenticationFilter.class); + return http.build(); + } @Bean public KerberosAuthenticationProvider kerberosAuthenticationProvider() { diff --git a/spring-security-kerberos-samples/sec-server-spnego-form-auth/src/main/resources/application.yml b/spring-security-kerberos-samples/sec-server-spnego-form-auth/src/main/resources/application.yml index eb94d2c..121c502 100644 --- a/spring-security-kerberos-samples/sec-server-spnego-form-auth/src/main/resources/application.yml +++ b/spring-security-kerberos-samples/sec-server-spnego-form-auth/src/main/resources/application.yml @@ -1,7 +1,7 @@ server: port: 8080 app: - service-principal: HTTP/cypher.localdomain@KERBOS.ORG + service-principal: HTTP/cypher.localdomain@KERBOS.COM keytab-location: /tmp/tomcat.keytab logging: level: