This is an automated email from the ASF dual-hosted git repository.

pefernan pushed a commit to branch quarkus-3.2LTS
in repository 
https://gitbox.apache.org/repos/asf/incubator-kie-kogito-runtimes.git


The following commit(s) were added to refs/heads/quarkus-3.2LTS by this push:
     new 419670c3e4 kie-issues#262: Spring-Boot 3.0.5 migration: Fix SVG Addon 
(#3303)
419670c3e4 is described below

commit 419670c3e4d0cf731381ef86da8e6bba8799a57e
Author: Pere Fernández <[email protected]>
AuthorDate: Fri Dec 1 14:48:43 2023 +0100

    kie-issues#262: Spring-Boot 3.0.5 migration: Fix SVG Addon (#3303)
    
    * kie-issues#262: Spring-Boot 3.0.5 migration: Fix SVG Addon
    * `keycloak-spring-boot-starter` removal in favour of springboot ouath2
    * IT test fixes
    * upgrade `quarkus-embedded-postgresql` version
---
 kogito-build/kogito-dependencies-bom/pom.xml       |  2 +-
 springboot/addons/process-svg/pom.xml              | 16 +------
 .../kogito/svg/auth/PrincipalAuthTokenReader.java  | 26 ++++++++++
 .../kie/kogito/svg/auth/SpringBootAuthHelper.java  | 56 ++++++++++++++++++++++
 .../svg/auth/impl/JwtPrincipalAuthTokenReader.java | 39 +++++++++++++++
 .../auth/impl/OIDCPrincipalAuthTokenReader.java    | 39 +++++++++++++++
 .../svg/dataindex/SpringBootDataIndexClient.java   | 38 ++++-----------
 .../dataindex/SpringBootDataIndexClientTest.java   | 47 +++++++++++++-----
 .../springboot/SignalProcessTest.java              |  4 +-
 9 files changed, 211 insertions(+), 56 deletions(-)

diff --git a/kogito-build/kogito-dependencies-bom/pom.xml 
b/kogito-build/kogito-dependencies-bom/pom.xml
index 4b22a07ddf..bff9397dce 100644
--- a/kogito-build/kogito-dependencies-bom/pom.xml
+++ b/kogito-build/kogito-dependencies-bom/pom.xml
@@ -32,7 +32,7 @@
     
<version.io.quarkiverse.openapi.generator>2.2.9</version.io.quarkiverse.openapi.generator>
     <version.io.quarkiverse.asyncapi>0.2.0</version.io.quarkiverse.asyncapi>
     
<version.io.quarkiverse.reactivemessaging.http>2.0.2</version.io.quarkiverse.reactivemessaging.http>
-    
<version.io.quarkiverse.embedded.postgresql>0.0.9</version.io.quarkiverse.embedded.postgresql>
+    
<version.io.quarkiverse.embedded.postgresql>0.1.0</version.io.quarkiverse.embedded.postgresql>
     
<version.com.github.haifengl.smile>1.5.2</version.com.github.haifengl.smile>
     <version.com.github.javaparser>3.25.1</version.com.github.javaparser>
     
<version.com.fasterxml.jackson.datatype>2.15.2</version.com.fasterxml.jackson.datatype>
diff --git a/springboot/addons/process-svg/pom.xml 
b/springboot/addons/process-svg/pom.xml
index ff6a94dbdd..6f415f81d4 100644
--- a/springboot/addons/process-svg/pom.xml
+++ b/springboot/addons/process-svg/pom.xml
@@ -31,18 +31,6 @@
   <name>Kogito :: Add-Ons :: Process SVG :: Spring Boot Addon</name>
   <description>Springboot Addon to interact with Process SVG 
Service</description>
 
-  <dependencyManagement>
-    <dependencies>
-      <dependency>
-        <groupId>org.keycloak.bom</groupId>
-        <artifactId>keycloak-adapter-bom</artifactId>
-        <version>${version.org.keycloak}</version>
-        <type>pom</type>
-        <scope>import</scope>
-      </dependency>
-    </dependencies>
-  </dependencyManagement>
-
   <dependencies>
     <dependency>
       <groupId>org.kie.kogito</groupId>
@@ -62,8 +50,8 @@
       <scope>provided</scope>
     </dependency>
     <dependency>
-      <groupId>org.keycloak</groupId>
-      <artifactId>keycloak-spring-boot-starter</artifactId>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-oauth2-client</artifactId>
       <scope>provided</scope>
     </dependency>
     <dependency>
diff --git 
a/springboot/addons/process-svg/src/main/java/org/kie/kogito/svg/auth/PrincipalAuthTokenReader.java
 
b/springboot/addons/process-svg/src/main/java/org/kie/kogito/svg/auth/PrincipalAuthTokenReader.java
new file mode 100644
index 0000000000..7a24ec72b9
--- /dev/null
+++ 
b/springboot/addons/process-svg/src/main/java/org/kie/kogito/svg/auth/PrincipalAuthTokenReader.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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
+ *
+ *   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.
+ */
+package org.kie.kogito.svg.auth;
+
+public interface PrincipalAuthTokenReader<T> {
+
+    boolean acceptsPrincipal(Object principal);
+
+    String readToken(T principal);
+}
diff --git 
a/springboot/addons/process-svg/src/main/java/org/kie/kogito/svg/auth/SpringBootAuthHelper.java
 
b/springboot/addons/process-svg/src/main/java/org/kie/kogito/svg/auth/SpringBootAuthHelper.java
new file mode 100644
index 0000000000..ef73f791d2
--- /dev/null
+++ 
b/springboot/addons/process-svg/src/main/java/org/kie/kogito/svg/auth/SpringBootAuthHelper.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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
+ *
+ *   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.
+ */
+package org.kie.kogito.svg.auth;
+
+import java.util.List;
+import java.util.Optional;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Component;
+
+@Component
+@ConditionalOnClass({ SecurityContextHolder.class })
+public class SpringBootAuthHelper {
+
+    private List<PrincipalAuthTokenReader> authTokenReaders;
+
+    public SpringBootAuthHelper(@Autowired List<PrincipalAuthTokenReader> 
authTokenReaders) {
+        this.authTokenReaders = authTokenReaders;
+    }
+
+    public Optional<String> getAuthToken() {
+        return Optional.ofNullable(getToken());
+    }
+
+    private String getToken() {
+        SecurityContext securityContext = SecurityContextHolder.getContext();
+
+        if (securityContext == null || securityContext.getAuthentication() == 
null) {
+            return null;
+        }
+
+        Object principal = securityContext.getAuthentication().getPrincipal();
+
+        return this.authTokenReaders.stream().filter(reader -> 
reader.acceptsPrincipal(principal)).findFirst()
+                .map(reader -> "Bearer " + 
reader.readToken(principal)).orElse(null);
+    }
+}
diff --git 
a/springboot/addons/process-svg/src/main/java/org/kie/kogito/svg/auth/impl/JwtPrincipalAuthTokenReader.java
 
b/springboot/addons/process-svg/src/main/java/org/kie/kogito/svg/auth/impl/JwtPrincipalAuthTokenReader.java
new file mode 100644
index 0000000000..dcb91f44a6
--- /dev/null
+++ 
b/springboot/addons/process-svg/src/main/java/org/kie/kogito/svg/auth/impl/JwtPrincipalAuthTokenReader.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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
+ *
+ *   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.
+ */
+package org.kie.kogito.svg.auth.impl;
+
+import org.kie.kogito.svg.auth.PrincipalAuthTokenReader;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.security.oauth2.jwt.Jwt;
+import org.springframework.stereotype.Component;
+
+@Component
+@ConditionalOnClass(Jwt.class)
+public class JwtPrincipalAuthTokenReader implements 
PrincipalAuthTokenReader<Jwt> {
+
+    @Override
+    public boolean acceptsPrincipal(Object principal) {
+        return principal instanceof Jwt;
+    }
+
+    @Override
+    public String readToken(Jwt principal) {
+        return principal.getTokenValue();
+    }
+}
diff --git 
a/springboot/addons/process-svg/src/main/java/org/kie/kogito/svg/auth/impl/OIDCPrincipalAuthTokenReader.java
 
b/springboot/addons/process-svg/src/main/java/org/kie/kogito/svg/auth/impl/OIDCPrincipalAuthTokenReader.java
new file mode 100644
index 0000000000..1187f44c60
--- /dev/null
+++ 
b/springboot/addons/process-svg/src/main/java/org/kie/kogito/svg/auth/impl/OIDCPrincipalAuthTokenReader.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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
+ *
+ *   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.
+ */
+package org.kie.kogito.svg.auth.impl;
+
+import org.kie.kogito.svg.auth.PrincipalAuthTokenReader;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.security.oauth2.core.oidc.user.OidcUser;
+import org.springframework.stereotype.Component;
+
+@Component
+@ConditionalOnClass({ OidcUser.class })
+public class OIDCPrincipalAuthTokenReader implements 
PrincipalAuthTokenReader<OidcUser> {
+
+    @Override
+    public boolean acceptsPrincipal(Object principal) {
+        return principal instanceof OidcUser;
+    }
+
+    @Override
+    public String readToken(OidcUser principal) {
+        return principal.getIdToken().getTokenValue();
+    }
+}
diff --git 
a/springboot/addons/process-svg/src/main/java/org/kie/kogito/svg/dataindex/SpringBootDataIndexClient.java
 
b/springboot/addons/process-svg/src/main/java/org/kie/kogito/svg/dataindex/SpringBootDataIndexClient.java
index 69f490e5ce..8f165cb170 100644
--- 
a/springboot/addons/process-svg/src/main/java/org/kie/kogito/svg/dataindex/SpringBootDataIndexClient.java
+++ 
b/springboot/addons/process-svg/src/main/java/org/kie/kogito/svg/dataindex/SpringBootDataIndexClient.java
@@ -20,10 +20,10 @@ package org.kie.kogito.svg.dataindex;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Optional;
 
-import jakarta.annotation.PostConstruct;
-import org.keycloak.KeycloakPrincipal;
 import org.kie.kogito.svg.ProcessSVGException;
+import org.kie.kogito.svg.auth.SpringBootAuthHelper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -32,8 +32,6 @@ import org.springframework.http.HttpEntity;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
-import org.springframework.security.core.context.SecurityContext;
-import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.stereotype.Component;
 import org.springframework.util.MultiValueMap;
 import org.springframework.web.client.RestTemplate;
@@ -41,6 +39,8 @@ import org.springframework.web.client.RestTemplate;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 
+import jakarta.annotation.PostConstruct;
+
 import static java.util.Collections.emptyList;
 import static java.util.Collections.singletonMap;
 
@@ -53,16 +53,18 @@ public class SpringBootDataIndexClient implements 
DataIndexClient {
     private RestTemplate restTemplate;
     private ObjectMapper objectMapper;
 
-    private boolean isKeycloakAdapterAvailable = false;
+    private Optional<SpringBootAuthHelper> authHelper;
 
     @Autowired
     public SpringBootDataIndexClient(
             @Value("${kogito.dataindex.http.url:http://localhost:8180}";) 
String dataIndexHttpURL,
             @Autowired(required = false) RestTemplate restTemplate,
-            @Autowired ObjectMapper objectMapper) {
+            @Autowired ObjectMapper objectMapper,
+            @Autowired Optional<SpringBootAuthHelper> authHelper) {
         this.dataIndexHttpURL = dataIndexHttpURL;
         this.restTemplate = restTemplate;
         this.objectMapper = objectMapper;
+        this.authHelper = authHelper;
     }
 
     @PostConstruct
@@ -71,21 +73,6 @@ public class SpringBootDataIndexClient implements 
DataIndexClient {
             restTemplate = new RestTemplate();
             LOGGER.debug("No RestTemplate found, creating a default one");
         }
-        try {
-            
Class.forName("org.springframework.security.core.context.SecurityContextHolder");
-            Class.forName("org.keycloak.KeycloakPrincipal");
-            setKeycloakAdapterAvailable(true);
-        } catch (ClassNotFoundException exception) {
-            LOGGER.debug("No Keycloak Adapter available, continue just 
propagating received authorization header");
-        }
-    }
-
-    public boolean isKeycloakAdapterAvailable() {
-        return isKeycloakAdapterAvailable;
-    }
-
-    public void setKeycloakAdapterAvailable(boolean keycloakAdapterAvailable) {
-        isKeycloakAdapterAvailable = keycloakAdapterAvailable;
     }
 
     @Override
@@ -120,13 +107,8 @@ public class SpringBootDataIndexClient implements 
DataIndexClient {
     }
 
     protected String getAuthHeader(String authHeader) {
-        if (isKeycloakAdapterAvailable()) {
-            SecurityContext securityContext = 
SecurityContextHolder.getContext();
-            if (securityContext != null &&
-                    securityContext.getAuthentication() != null &&
-                    securityContext.getAuthentication().getPrincipal() 
instanceof KeycloakPrincipal) {
-                return "Bearer " + ((KeycloakPrincipal) 
securityContext.getAuthentication().getPrincipal()).getKeycloakSecurityContext().getTokenString();
-            }
+        if (authHelper.isPresent()) {
+            return authHelper.get().getAuthToken().orElse(authHeader);
         }
         return authHeader;
     }
diff --git 
a/springboot/addons/process-svg/src/test/java/org/kie/kogito/svg/dataindex/SpringBootDataIndexClientTest.java
 
b/springboot/addons/process-svg/src/test/java/org/kie/kogito/svg/dataindex/SpringBootDataIndexClientTest.java
index 6a613d8ae8..ac50a77770 100644
--- 
a/springboot/addons/process-svg/src/test/java/org/kie/kogito/svg/dataindex/SpringBootDataIndexClientTest.java
+++ 
b/springboot/addons/process-svg/src/test/java/org/kie/kogito/svg/dataindex/SpringBootDataIndexClientTest.java
@@ -19,13 +19,15 @@
 package org.kie.kogito.svg.dataindex;
 
 import java.util.List;
+import java.util.Optional;
 
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
-import org.keycloak.KeycloakPrincipal;
-import org.keycloak.KeycloakSecurityContext;
 import org.kie.kogito.svg.ProcessSVGException;
+import org.kie.kogito.svg.auth.SpringBootAuthHelper;
+import org.kie.kogito.svg.auth.impl.JwtPrincipalAuthTokenReader;
+import org.kie.kogito.svg.auth.impl.OIDCPrincipalAuthTokenReader;
 import org.mockito.Mock;
 import org.mockito.junit.jupiter.MockitoExtension;
 import org.springframework.http.HttpEntity;
@@ -33,6 +35,9 @@ import org.springframework.http.ResponseEntity;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.context.SecurityContext;
 import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.oauth2.core.oidc.OidcIdToken;
+import org.springframework.security.oauth2.core.oidc.user.OidcUser;
+import org.springframework.security.oauth2.jwt.Jwt;
 import org.springframework.web.client.HttpClientErrorException;
 import org.springframework.web.client.RestTemplate;
 
@@ -80,7 +85,11 @@ public class SpringBootDataIndexClientTest {
 
     @BeforeEach
     void setUp() {
-        client = new SpringBootDataIndexClient("data-indexURL", restTemplate, 
objectMapper);
+        client = buildClient(Optional.empty());
+    }
+
+    private SpringBootDataIndexClient 
buildClient(Optional<SpringBootAuthHelper> authHelper) {
+        return new SpringBootDataIndexClient("data-indexURL", restTemplate, 
objectMapper, authHelper);
     }
 
     @Test
@@ -117,27 +126,43 @@ public class SpringBootDataIndexClientTest {
     }
 
     @Test
-    public void testAuthHeaderWithSecurityContext() {
+    public void testAuthHeaderWithSecurityContextOidcUserPrincipal() {
+        String token = "testToken";
+        SecurityContext securityContextMock = mock(SecurityContext.class);
+        Authentication authenticationMock = mock(Authentication.class);
+        OidcUser principalMock = mock(OidcUser.class);
+        OidcIdToken tokenMock = mock(OidcIdToken.class);
+
+        
when(securityContextMock.getAuthentication()).thenReturn(authenticationMock);
+        when(authenticationMock.getPrincipal()).thenReturn(principalMock);
+        when(principalMock.getIdToken()).thenReturn(tokenMock);
+        when(tokenMock.getTokenValue()).thenReturn(token);
+
+        SecurityContextHolder.setContext(securityContextMock);
+        client = buildClient(Optional.of(new SpringBootAuthHelper(List.of(new 
OIDCPrincipalAuthTokenReader(), new JwtPrincipalAuthTokenReader()))));
+        assertThat(client.getAuthHeader("")).isEqualTo("Bearer " + token);
+    }
+
+    @Test
+    public void testAuthHeaderWithSecurityContextJwtPrincipal() {
         String token = "testToken";
         SecurityContext securityContextMock = mock(SecurityContext.class);
         Authentication authenticationMock = mock(Authentication.class);
-        KeycloakPrincipal principalMock = mock(KeycloakPrincipal.class);
-        KeycloakSecurityContext keycloakSecurityContextMock = 
mock(KeycloakSecurityContext.class);
+        Jwt principalMock = mock(Jwt.class);
 
         
when(securityContextMock.getAuthentication()).thenReturn(authenticationMock);
         when(authenticationMock.getPrincipal()).thenReturn(principalMock);
-        
when(principalMock.getKeycloakSecurityContext()).thenReturn(keycloakSecurityContextMock);
-        when(keycloakSecurityContextMock.getTokenString()).thenReturn(token);
+        when(principalMock.getTokenValue()).thenReturn(token);
 
         SecurityContextHolder.setContext(securityContextMock);
-        client.setKeycloakAdapterAvailable(true);
+        client = buildClient(Optional.of(new SpringBootAuthHelper(List.of(new 
OIDCPrincipalAuthTokenReader(), new JwtPrincipalAuthTokenReader()))));
         assertThat(client.getAuthHeader("")).isEqualTo("Bearer " + token);
     }
 
     @Test
-    public void testAuthHeaderWithoutKeycloakSecurityContext() {
+    public void testAuthHeaderWithoutSecurityContext() {
         String authHeader = "Bearer testToken";
-        client.setKeycloakAdapterAvailable(false);
+        client = buildClient(Optional.of(new SpringBootAuthHelper(List.of(new 
OIDCPrincipalAuthTokenReader(), new JwtPrincipalAuthTokenReader()))));
         assertThat(client.getAuthHeader(authHeader)).isEqualTo(authHeader);
     }
 }
diff --git 
a/springboot/integration-tests/src/it/integration-tests-springboot-processes-it/src/test/java/org/kie/kogito/integrationtests/springboot/SignalProcessTest.java
 
b/springboot/integration-tests/src/it/integration-tests-springboot-processes-it/src/test/java/org/kie/kogito/integrationtests/springboot/SignalProcessTest.java
index 8cdb8bb6cb..ba7515c73b 100644
--- 
a/springboot/integration-tests/src/it/integration-tests-springboot-processes-it/src/test/java/org/kie/kogito/integrationtests/springboot/SignalProcessTest.java
+++ 
b/springboot/integration-tests/src/it/integration-tests-springboot-processes-it/src/test/java/org/kie/kogito/integrationtests/springboot/SignalProcessTest.java
@@ -48,10 +48,10 @@ class SignalProcessTest extends BaseRestTest {
         given()
                 .contentType(ContentType.JSON)
                 .when()
-                .get("/signalStart/")
+                .get("/signalStart")
                 .then()
                 .statusCode(200)
-                .body("$.size()", is(1))
+                .body("size()", is(1))
                 .body("[0].message", equalTo("hello world"));
     }
     @Test


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to