From 55d5e790ab549359848bd1100c6aacee26ce038f Mon Sep 17 00:00:00 2001 From: "EVOFORGE\\dimay" Date: Mon, 6 Nov 2023 10:42:07 -0500 Subject: [PATCH 1/6] #2462: truststore was not loading for tests when using autowired version of RestTemplate --- service/src/main/java/skills/auth/pki/PkiUserLookup.groovy | 5 ++--- .../java/skills/intTests/utils/MockUserInfoService.groovy | 6 +++--- service/src/test/resources/application-pki.properties | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/service/src/main/java/skills/auth/pki/PkiUserLookup.groovy b/service/src/main/java/skills/auth/pki/PkiUserLookup.groovy index bd9fb0c423..2261dc37e8 100644 --- a/service/src/main/java/skills/auth/pki/PkiUserLookup.groovy +++ b/service/src/main/java/skills/auth/pki/PkiUserLookup.groovy @@ -24,7 +24,6 @@ import groovy.util.logging.Slf4j import jakarta.annotation.PostConstruct import jakarta.annotation.PreDestroy import jakarta.servlet.http.HttpServletRequest -import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Value import org.springframework.context.annotation.Conditional import org.springframework.core.ParameterizedTypeReference @@ -47,8 +46,8 @@ import java.util.concurrent.TimeUnit class PkiUserLookup { // use @Autowired if you want to utilize apache HttpClient (see HttpClientRestTemplateConfig) - @Autowired - RestTemplate restTemplate // = new RestTemplate() +// @Autowired + RestTemplate restTemplate = new RestTemplate() @Value('${skills.authorization.userInfoUri}') String userInfoUri diff --git a/service/src/test/java/skills/intTests/utils/MockUserInfoService.groovy b/service/src/test/java/skills/intTests/utils/MockUserInfoService.groovy index 3128a2b0da..dd3eb7fd31 100644 --- a/service/src/test/java/skills/intTests/utils/MockUserInfoService.groovy +++ b/service/src/test/java/skills/intTests/utils/MockUserInfoService.groovy @@ -70,7 +70,7 @@ public class MockUserInfoService { @PostConstruct void start() { - def matcher = userInfoHealthCheckUri =~ /https:\/\/localhost:(\d\d\d\d)\/actuator\/health/ + def matcher = userInfoHealthCheckUri =~ /https:\/\/localhost:(\d\d\d\d)\/status/ int port = Integer.parseInt(matcher[0][1]); log.info("starting mock user-info-service on port ${port}") @@ -88,10 +88,10 @@ public class MockUserInfoService { .needClientAuth(true) .extensions(new UserInfoResponseTransformer(userAttrsRepo))); - mockServer.stubFor(any(urlPathEqualTo("/actuator/health")).willReturn( + mockServer.stubFor(any(urlPathEqualTo("/status")).willReturn( ok() .withHeader(CONTENT_TYPE, "application/json") - .withBody("""{ "status": "UP" }""") + .withBody("""{ "status": "OK" }""") )); mockServer.stubFor(any(urlPathEqualTo("/userQuery")).willReturn( ok() diff --git a/service/src/test/resources/application-pki.properties b/service/src/test/resources/application-pki.properties index a23ae90031..63720b3191 100644 --- a/service/src/test/resources/application-pki.properties +++ b/service/src/test/resources/application-pki.properties @@ -51,7 +51,7 @@ server.ssl.enabled-protocols=TLSv1.2 skills.disableHostnameVerifier=true skills.authorization.userInfoUri=https://localhost:8181/userInfo?dn={dn} skills.authorization.userQueryUri=https://localhost:8181/userQuery?query={query} -skills.authorization.userInfoHealthCheckUri=https://localhost:8181/actuator/health +skills.authorization.userInfoHealthCheckUri=https://localhost:8181/status skills.authorization.authMode=PKI skills.config.notifications.dispatchSchedule=*/5 * * * * * From 6ab8777b6825be7ef3c25697edc200e13bda32f3 Mon Sep 17 00:00:00 2001 From: "EVOFORGE\\dimay" Date: Mon, 6 Nov 2023 11:29:59 -0500 Subject: [PATCH 2/6] #2462: fixing status url --- .../skills/intTests/RankingAndProgressViewsDisabledIT.groovy | 2 +- service/src/test/java/skills/intTests/ServerTimingApiIT.groovy | 2 +- .../test/java/skills/intTests/UpdtedDefaultHomePageIT.groovy | 2 +- .../src/test/java/skills/intTests/UpgradeInProgressIT.groovy | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/service/src/test/java/skills/intTests/RankingAndProgressViewsDisabledIT.groovy b/service/src/test/java/skills/intTests/RankingAndProgressViewsDisabledIT.groovy index d1f3994413..8aa5f9931c 100644 --- a/service/src/test/java/skills/intTests/RankingAndProgressViewsDisabledIT.groovy +++ b/service/src/test/java/skills/intTests/RankingAndProgressViewsDisabledIT.groovy @@ -26,7 +26,7 @@ import skills.intTests.utils.SkillsFactory @SpringBootTest(properties = ['skills.h2.port=9091', 'skills.config.ui.rankingAndProgressViewsEnabled=false', 'skills.config.ui.defaultLandingPage=progress', 'skills.authorization.userInfoUri=https://localhost:8182/userInfo?dn={dn}', 'skills.authorization.userQueryUri=https://localhost:8182/userQuery?query={query}', - 'skills.authorization.userInfoHealthCheckUri=https://localhost:8182/actuator/health'], webEnvironment=SpringBootTest.WebEnvironment.RANDOM_PORT, classes = SpringBootApp) + 'skills.authorization.userInfoHealthCheckUri=https://localhost:8182/status'], webEnvironment=SpringBootTest.WebEnvironment.RANDOM_PORT, classes = SpringBootApp) class RankingAndProgressViewsDisabledIT extends DefaultIntSpec { def "landingPage page is always admin when rankingAndProgressViewsDisabled=true"() { diff --git a/service/src/test/java/skills/intTests/ServerTimingApiIT.groovy b/service/src/test/java/skills/intTests/ServerTimingApiIT.groovy index 6ac2ba515c..2abb092036 100644 --- a/service/src/test/java/skills/intTests/ServerTimingApiIT.groovy +++ b/service/src/test/java/skills/intTests/ServerTimingApiIT.groovy @@ -23,7 +23,7 @@ import skills.intTests.utils.DefaultIntSpec @SpringBootTest(properties = ['skills.prof.serverTimingAPI.enabled=false', 'skills.authorization.userInfoUri=https://localhost:8183/userInfo?dn={dn}', 'skills.authorization.userQueryUri=https://localhost:8183/userQuery?query={query}', - 'skills.authorization.userInfoHealthCheckUri=https://localhost:8183/actuator/health'], + 'skills.authorization.userInfoHealthCheckUri=https://localhost:8183/status'], webEnvironment=SpringBootTest.WebEnvironment.RANDOM_PORT, classes = SpringBootApp) class ServerTimingApiIT extends DefaultIntSpec { diff --git a/service/src/test/java/skills/intTests/UpdtedDefaultHomePageIT.groovy b/service/src/test/java/skills/intTests/UpdtedDefaultHomePageIT.groovy index 1ea1b8a624..4832c409b8 100644 --- a/service/src/test/java/skills/intTests/UpdtedDefaultHomePageIT.groovy +++ b/service/src/test/java/skills/intTests/UpdtedDefaultHomePageIT.groovy @@ -27,7 +27,7 @@ import skills.intTests.utils.DefaultIntSpec 'skills.config.ui.defaultLandingPage=progress', 'skills.authorization.userInfoUri=https://localhost:8184/userInfo?dn={dn}', 'skills.authorization.userQueryUri=https://localhost:8184/userQuery?query={query}', - 'skills.authorization.userInfoHealthCheckUri=https://localhost:8184/actuator/health'], webEnvironment=SpringBootTest.WebEnvironment.RANDOM_PORT, classes = SpringBootApp) + 'skills.authorization.userInfoHealthCheckUri=https://localhost:8184/status'], webEnvironment=SpringBootTest.WebEnvironment.RANDOM_PORT, classes = SpringBootApp) class UpdtedDefaultHomePageIT extends DefaultIntSpec { def "landingPage page is always admin when rankingAndProgressViewsDisabled=true"() { diff --git a/service/src/test/java/skills/intTests/UpgradeInProgressIT.groovy b/service/src/test/java/skills/intTests/UpgradeInProgressIT.groovy index e941e1ea79..6237c80dd2 100644 --- a/service/src/test/java/skills/intTests/UpgradeInProgressIT.groovy +++ b/service/src/test/java/skills/intTests/UpgradeInProgressIT.groovy @@ -47,7 +47,7 @@ import skills.storage.repos.UserRepo 'skills.config.ui.rankingAndProgressViewsEnabled=false', 'skills.config.ui.defaultLandingPage=progress', 'skills.config.db-upgrade-in-progress=true', - 'skills.authorization.userInfoHealthCheckUri=https://localhost:8189/actuator/health', + 'skills.authorization.userInfoHealthCheckUri=https://localhost:8189/status', 'skills.authorization.userInfoUri=https://localhost:8189/userInfo?dn={dn}', 'skills.authorization.userQueryUri=https://localhost:8189/userQuery?query={query}', ], webEnvironment=SpringBootTest.WebEnvironment.RANDOM_PORT, classes = SpringBootApp) From ef3ac416da01e7910442abe97cec1b14bc5a20d3 Mon Sep 17 00:00:00 2001 From: "EVOFORGE\\dimay" Date: Mon, 6 Nov 2023 12:21:48 -0500 Subject: [PATCH 3/6] #2462: run ssl workflow on pull request --- .github/workflows/build-and-test-ssl.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/build-and-test-ssl.yml b/.github/workflows/build-and-test-ssl.yml index 8d2c348303..79f38ef17a 100644 --- a/.github/workflows/build-and-test-ssl.yml +++ b/.github/workflows/build-and-test-ssl.yml @@ -18,6 +18,12 @@ on: schedule: - cron: '0 7 * * *' workflow_dispatch: + pull_request: + paths-ignore: + - 'README.md' + - '.github/workflows/build-and-test-postgres.yml' + - '.github/workflows/publish-image-snapshot.yml' + - '.gitlab-ci.yml' jobs: From 9fed9a59043bff25b9c5ee112b4aabfcb007a54e Mon Sep 17 00:00:00 2001 From: rmmayo Date: Fri, 10 Nov 2023 10:30:22 -0500 Subject: [PATCH 4/6] #2462 - override default SSLContext which may have already been initialized --- .../java/skills/intTests/utils/SystemSSLConfiguration.groovy | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/service/src/test/java/skills/intTests/utils/SystemSSLConfiguration.groovy b/service/src/test/java/skills/intTests/utils/SystemSSLConfiguration.groovy index b3f6efd00c..5cbace0458 100644 --- a/service/src/test/java/skills/intTests/utils/SystemSSLConfiguration.groovy +++ b/service/src/test/java/skills/intTests/utils/SystemSSLConfiguration.groovy @@ -24,6 +24,8 @@ import skills.auth.SecurityMode import jakarta.annotation.PostConstruct +import javax.net.ssl.SSLContext + @Slf4j @Conditional(SecurityMode.PkiAuth) @Component @@ -54,6 +56,9 @@ class SystemSSLConfiguration { System.setProperty("javax.net.ssl.trustStore", trustFile.getPath()) System.setProperty("javax.net.ssl.trustStorePassword", trustStorePassword) System.setProperty("javax.net.ssl.trustStoreType", trustStoreType) + + // override any existing default SSLContext + SSLContext.setDefault(SSLContext.getInstance("Default")) } } } From 15d065f90646db06b38cbb0fe37cdf84d14ec983 Mon Sep 17 00:00:00 2001 From: rmmayo Date: Fri, 10 Nov 2023 14:09:19 -0500 Subject: [PATCH 5/6] #2462 - replace requestFactory in the RestTemplate bean --- .../pki/HttpClientRestTemplateConfig.groovy | 4 ++ .../utils/SystemSSLConfiguration.groovy | 49 +++++++++++++++++-- 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/service/src/main/java/skills/auth/pki/HttpClientRestTemplateConfig.groovy b/service/src/main/java/skills/auth/pki/HttpClientRestTemplateConfig.groovy index 7219ec4504..a4e94ced13 100644 --- a/service/src/main/java/skills/auth/pki/HttpClientRestTemplateConfig.groovy +++ b/service/src/main/java/skills/auth/pki/HttpClientRestTemplateConfig.groovy @@ -67,6 +67,10 @@ class HttpClientRestTemplateConfig { @Bean PoolingHttpClientConnectionManager poolingHttpClientConnectionManager() { + return createPoolingHttpClientConnectionManager(); + } + + PoolingHttpClientConnectionManager createPoolingHttpClientConnectionManager() { SSLContext sslContext = SSLContexts.createSystemDefault() HostnameVerifier allowAllHosts = new NoopHostnameVerifier(); SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory( diff --git a/service/src/test/java/skills/intTests/utils/SystemSSLConfiguration.groovy b/service/src/test/java/skills/intTests/utils/SystemSSLConfiguration.groovy index 5cbace0458..a661b6407f 100644 --- a/service/src/test/java/skills/intTests/utils/SystemSSLConfiguration.groovy +++ b/service/src/test/java/skills/intTests/utils/SystemSSLConfiguration.groovy @@ -16,15 +16,24 @@ package skills.intTests.utils import groovy.util.logging.Slf4j +import jakarta.annotation.PostConstruct +import org.apache.hc.client5.http.classic.HttpClient +import org.apache.hc.client5.http.impl.classic.HttpClients +import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Value import org.springframework.context.annotation.Conditional +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory import org.springframework.stereotype.Component import org.springframework.util.ResourceUtils +import org.springframework.web.client.RestTemplate import skills.auth.SecurityMode +import skills.auth.pki.HttpClientRestTemplateConfig -import jakarta.annotation.PostConstruct - +import javax.net.ssl.HttpsURLConnection +import javax.net.ssl.KeyManagerFactory import javax.net.ssl.SSLContext +import javax.net.ssl.TrustManagerFactory +import java.security.KeyStore @Slf4j @Conditional(SecurityMode.PkiAuth) @@ -44,8 +53,14 @@ class SystemSSLConfiguration { @Value('#{"${server.ssl.trustStoreType}"}') String trustStoreType + @Autowired + HttpClientRestTemplateConfig rtc + + @Autowired + RestTemplate restTemplate + @PostConstruct - public void init() { + void init() { if (keyStore) { log.info("Setting system ssl properties for integration tests") File ksFile = ResourceUtils.getFile(keyStore) @@ -58,7 +73,33 @@ class SystemSSLConfiguration { System.setProperty("javax.net.ssl.trustStoreType", trustStoreType) // override any existing default SSLContext - SSLContext.setDefault(SSLContext.getInstance("Default")) + KeyStore keyStoreObj = KeyStore.getInstance("JKS"); + keyStoreObj.load(new FileInputStream(ksFile), keyStorePassword.toCharArray()); + + // Set up key manager factory to use our key store + KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + keyManagerFactory.init(keyStoreObj, keyStorePassword.toCharArray()); + + // truststore + KeyStore trustStoreObj = KeyStore.getInstance("JKS"); + trustStoreObj.load(new FileInputStream(trustFile), trustStorePassword.toCharArray()); + + TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + trustManagerFactory.init(trustStoreObj); + + SSLContext ctx = SSLContext.getInstance("TLS"); + ctx.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null); + SSLContext.setDefault(ctx); + + HttpsURLConnection.setDefaultSSLSocketFactory(ctx.getSocketFactory()); + HttpClient httpClient = HttpClients.custom() + .useSystemProperties() + .setConnectionManager(rtc.createPoolingHttpClientConnectionManager()) + .setDefaultRequestConfig(rtc.requestConfig()) + .build() + HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory() + requestFactory.setHttpClient(httpClient) + restTemplate.setRequestFactory(requestFactory) } } } From 6e9fd68871417dd6ba80814abe28ac66a7918c4a Mon Sep 17 00:00:00 2001 From: rmmayo Date: Fri, 10 Nov 2023 14:24:58 -0500 Subject: [PATCH 6/6] #2462 - use the HttpClient configured RestTemplate bean --- service/src/main/java/skills/auth/pki/PkiUserLookup.groovy | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/service/src/main/java/skills/auth/pki/PkiUserLookup.groovy b/service/src/main/java/skills/auth/pki/PkiUserLookup.groovy index 2261dc37e8..2cfe339bcc 100644 --- a/service/src/main/java/skills/auth/pki/PkiUserLookup.groovy +++ b/service/src/main/java/skills/auth/pki/PkiUserLookup.groovy @@ -24,6 +24,7 @@ import groovy.util.logging.Slf4j import jakarta.annotation.PostConstruct import jakarta.annotation.PreDestroy import jakarta.servlet.http.HttpServletRequest +import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Value import org.springframework.context.annotation.Conditional import org.springframework.core.ParameterizedTypeReference @@ -46,8 +47,8 @@ import java.util.concurrent.TimeUnit class PkiUserLookup { // use @Autowired if you want to utilize apache HttpClient (see HttpClientRestTemplateConfig) -// @Autowired - RestTemplate restTemplate = new RestTemplate() + @Autowired + RestTemplate restTemplate @Value('${skills.authorization.userInfoUri}') String userInfoUri