You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@streampipes.apache.org by ri...@apache.org on 2022/04/25 12:07:46 UTC
[incubator-streampipes] branch dev updated: [STREAMPIPES-534] Add support for authenticated extension services
This is an automated email from the ASF dual-hosted git repository.
riemer pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/incubator-streampipes.git
The following commit(s) were added to refs/heads/dev by this push:
new 3fd875939 [STREAMPIPES-534] Add support for authenticated extension services
3fd875939 is described below
commit 3fd8759399b51d7753d893d2ccf348107fc40e2b
Author: Dominik Riemer <do...@gmail.com>
AuthorDate: Mon Apr 25 14:07:36 2022 +0200
[STREAMPIPES-534] Add support for authenticated extension services
---
pom.xml | 5 ++
.../streampipes/backend/WebSecurityConfig.java | 3 +-
.../apache/streampipes/commons/constants/Envs.java | 1 +
streampipes-connect-container-worker/pom.xml | 7 ++
.../extensions/ExtensionsModelSubmitter.java | 3 +-
.../org/apache/streampipes/model}/UserInfo.java | 2 +-
.../impl/admin/GeneralConfigurationResource.java | 2 +-
.../streampipes/security/jwt/JwtTokenUtils.java | 5 ++
.../streampipes/security/jwt/KeyGenerator.java | 3 +-
.../security/jwt/PublicKeyResolver.java | 30 ++++---
streampipes-service-base/pom.xml | 4 +
.../service/base/rest/BaseResourceConfig.java | 2 +
.../security}/UnauthorizedRequestEntryPoint.java | 4 +-
.../extensions/base}/WebSecurityConfig.java | 83 +++++++++++--------
.../base/security/TokenAuthenticationFilter.java | 92 ++++++++++++++++++++++
.../base/security/UnauthenticatedInterfaces.java | 24 +++---
.../user/management/util/UserInfoUtil.java | 2 +-
.../src/lib/model/gen/streampipes-model-client.ts | 23 +-----
.../src/lib/model/gen/streampipes-model.ts | 29 ++++++-
19 files changed, 234 insertions(+), 90 deletions(-)
diff --git a/pom.xml b/pom.xml
index b43ff174d..e35c0f417 100644
--- a/pom.xml
+++ b/pom.xml
@@ -389,6 +389,11 @@ IoT data streams.
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
+ <dependency>
+ <groupId>net.minidev</groupId>
+ <artifactId>json-smart</artifactId>
+ <version>1.3.3</version>
+ </dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>fluent-hc</artifactId>
diff --git a/streampipes-backend/src/main/java/org/apache/streampipes/backend/WebSecurityConfig.java b/streampipes-backend/src/main/java/org/apache/streampipes/backend/WebSecurityConfig.java
index e882c8ceb..b33d9b07e 100644
--- a/streampipes-backend/src/main/java/org/apache/streampipes/backend/WebSecurityConfig.java
+++ b/streampipes-backend/src/main/java/org/apache/streampipes/backend/WebSecurityConfig.java
@@ -19,6 +19,7 @@
package org.apache.streampipes.backend;
import org.apache.streampipes.rest.filter.TokenAuthenticationFilter;
+import org.apache.streampipes.service.base.security.UnauthorizedRequestEntryPoint;
import org.apache.streampipes.user.management.service.SpUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
@@ -40,7 +41,7 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthentic
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private final UserDetailsService userDetailsService;
- private StreamPipesPasswordEncoder passwordEncoder;
+ private final StreamPipesPasswordEncoder passwordEncoder;
public WebSecurityConfig(StreamPipesPasswordEncoder passwordEncoder) {
this.passwordEncoder = passwordEncoder;
diff --git a/streampipes-commons/src/main/java/org/apache/streampipes/commons/constants/Envs.java b/streampipes-commons/src/main/java/org/apache/streampipes/commons/constants/Envs.java
index 954d3d953..217f649fd 100644
--- a/streampipes-commons/src/main/java/org/apache/streampipes/commons/constants/Envs.java
+++ b/streampipes-commons/src/main/java/org/apache/streampipes/commons/constants/Envs.java
@@ -32,6 +32,7 @@ public enum Envs {
SP_INITIAL_SERVICE_USER("SP_INITIAL_SERVICE_USER"),
SP_INITIAL_SERVICE_USER_SECRET("SP_INITIAL_SERVICE_USER_SECRET"),
SP_SETUP_INSTALL_PIPELINE_ELEMENTS("SP_SETUP_INSTALL_PIPELINE_ELEMENTS"),
+ SP_EXT_AUTH_MODE("SP_EXT_AUTH_MODE"),
SP_CLIENT_USER("SP_CLIENT_USER"),
SP_CLIENT_SECRET("SP_CLIENT_SECRET"),
SP_ENCRYPTION_PASSCODE("SP_ENCRYPTION_PASSCODE"),
diff --git a/streampipes-connect-container-worker/pom.xml b/streampipes-connect-container-worker/pom.xml
index 6b6b20700..dc1e74b88 100644
--- a/streampipes-connect-container-worker/pom.xml
+++ b/streampipes-connect-container-worker/pom.xml
@@ -66,6 +66,13 @@
</dependency>
<!-- External dependencies -->
+
+ <!-- Dependency convergence -->
+ <dependency>
+ <groupId>net.minidev</groupId>
+ <artifactId>json-smart</artifactId>
+ </dependency>
+
<!-- Test dependencies -->
<dependency>
<groupId>com.github.tomakehurst</groupId>
diff --git a/streampipes-container-extensions/src/main/java/org/apache/streampipes/container/extensions/ExtensionsModelSubmitter.java b/streampipes-container-extensions/src/main/java/org/apache/streampipes/container/extensions/ExtensionsModelSubmitter.java
index 63b8d1570..d0e97de0a 100644
--- a/streampipes-container-extensions/src/main/java/org/apache/streampipes/container/extensions/ExtensionsModelSubmitter.java
+++ b/streampipes-container-extensions/src/main/java/org/apache/streampipes/container/extensions/ExtensionsModelSubmitter.java
@@ -24,6 +24,7 @@ import org.apache.streampipes.container.model.SpServiceDefinition;
import org.apache.streampipes.container.standalone.init.PipelineElementServiceShutdownHandler;
import org.apache.streampipes.container.standalone.init.PipelineElementServiceTagProvider;
import org.apache.streampipes.service.extensions.base.StreamPipesExtensionsServiceBase;
+import org.apache.streampipes.service.extensions.base.WebSecurityConfig;
import org.apache.streampipes.svcdiscovery.api.model.SpServiceTag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -36,7 +37,7 @@ import java.util.List;
@Configuration
@EnableAutoConfiguration
-@Import({ ExtensionsResourceConfig.class })
+@Import({ ExtensionsResourceConfig.class, WebSecurityConfig.class})
public abstract class ExtensionsModelSubmitter extends StreamPipesExtensionsServiceBase {
private static final Logger LOG =
diff --git a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/UserInfo.java b/streampipes-model/src/main/java/org/apache/streampipes/model/UserInfo.java
similarity index 97%
rename from streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/UserInfo.java
rename to streampipes-model/src/main/java/org/apache/streampipes/model/UserInfo.java
index 4295f8497..9a8b200ae 100644
--- a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/UserInfo.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/UserInfo.java
@@ -15,7 +15,7 @@
* limitations under the License.
*
*/
-package org.apache.streampipes.model.client.user;
+package org.apache.streampipes.model;
import org.apache.streampipes.model.shared.annotation.TsModel;
diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/admin/GeneralConfigurationResource.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/admin/GeneralConfigurationResource.java
index ad41cc80d..91cd5ab9d 100644
--- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/admin/GeneralConfigurationResource.java
+++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/admin/GeneralConfigurationResource.java
@@ -78,7 +78,7 @@ public class GeneralConfigurationResource extends AbstractAuthGuardedRestResourc
return Response.ok(multiPartEntity).build();
}
- private String exportKeyAsPem(Key key, String keyType) throws Exception {
+ private String exportKeyAsPem(Key key, String keyType) {
StringWriter sw = new StringWriter();
sw.write("-----BEGIN " + keyType + " KEY-----\n");
diff --git a/streampipes-security-jwt/src/main/java/org/apache/streampipes/security/jwt/JwtTokenUtils.java b/streampipes-security-jwt/src/main/java/org/apache/streampipes/security/jwt/JwtTokenUtils.java
index 6163c61d1..1ea45ce8f 100644
--- a/streampipes-security-jwt/src/main/java/org/apache/streampipes/security/jwt/JwtTokenUtils.java
+++ b/streampipes-security-jwt/src/main/java/org/apache/streampipes/security/jwt/JwtTokenUtils.java
@@ -37,6 +37,11 @@ public class JwtTokenUtils {
return jwtParser(resolver).parseClaimsJws(token).getBody().getSubject();
}
+ public static Claims getClaimsFromToken(String token,
+ SigningKeyResolver resolver) {
+ return jwtParser(resolver).parseClaimsJws(token).getBody();
+ }
+
public static JwtParser jwtParser(String tokenSecret) {
return Jwts.parserBuilder()
.setSigningKey(tokenSecret.getBytes(StandardCharsets.UTF_8))
diff --git a/streampipes-security-jwt/src/main/java/org/apache/streampipes/security/jwt/KeyGenerator.java b/streampipes-security-jwt/src/main/java/org/apache/streampipes/security/jwt/KeyGenerator.java
index b62087147..bbd3f64ad 100644
--- a/streampipes-security-jwt/src/main/java/org/apache/streampipes/security/jwt/KeyGenerator.java
+++ b/streampipes-security-jwt/src/main/java/org/apache/streampipes/security/jwt/KeyGenerator.java
@@ -54,8 +54,7 @@ public class KeyGenerator {
try {
return makeKeyForRsa(pkContent);
} catch (IOException | InvalidKeySpecException | NoSuchAlgorithmException e) {
- e.printStackTrace();
- LOG.warn("Could not properly create the provided key, defaulting to an HMAC token, which will almost certainly lead to problems");
+ LOG.error("Could not properly create the provided key, defaulting to an HMAC token, which will almost certainly lead to problems");
return makeKeyForSecret(tokenSecret);
}
} else {
diff --git a/streampipes-service-base/src/main/java/org/apache/streampipes/service/base/rest/BaseResourceConfig.java b/streampipes-security-jwt/src/main/java/org/apache/streampipes/security/jwt/PublicKeyResolver.java
similarity index 56%
copy from streampipes-service-base/src/main/java/org/apache/streampipes/service/base/rest/BaseResourceConfig.java
copy to streampipes-security-jwt/src/main/java/org/apache/streampipes/security/jwt/PublicKeyResolver.java
index 2233be263..96c07e8ae 100644
--- a/streampipes-service-base/src/main/java/org/apache/streampipes/service/base/rest/BaseResourceConfig.java
+++ b/streampipes-security-jwt/src/main/java/org/apache/streampipes/security/jwt/PublicKeyResolver.java
@@ -15,20 +15,30 @@
* limitations under the License.
*
*/
-package org.apache.streampipes.service.base.rest;
-import org.glassfish.jersey.server.ResourceConfig;
+package org.apache.streampipes.security.jwt;
-import java.util.List;
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.JwsHeader;
+import io.jsonwebtoken.SigningKeyResolver;
-public abstract class BaseResourceConfig extends ResourceConfig {
+import java.io.IOException;
+import java.security.Key;
- public BaseResourceConfig() {
- getClassesToRegister()
- .forEach(set -> set.forEach(this::register));
- register(ServiceHealthResource.class);
- }
+public class PublicKeyResolver implements SigningKeyResolver {
- public abstract List<List<Class<?>>> getClassesToRegister();
+ @Override
+ public Key resolveSigningKey(JwsHeader jwsHeader, Claims claims) {
+ try {
+ return new KeyGenerator().makeKeyForSecret(jwsHeader.getAlgorithm(), "");
+ } catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+ @Override
+ public Key resolveSigningKey(JwsHeader jwsHeader, String s) {
+ return null;
+ }
}
diff --git a/streampipes-service-base/pom.xml b/streampipes-service-base/pom.xml
index fe03bad89..41e0ddfc5 100644
--- a/streampipes-service-base/pom.xml
+++ b/streampipes-service-base/pom.xml
@@ -67,6 +67,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-oauth2-client</artifactId>
+ </dependency>
<!--dependency convergence-->
<dependency>
diff --git a/streampipes-service-base/src/main/java/org/apache/streampipes/service/base/rest/BaseResourceConfig.java b/streampipes-service-base/src/main/java/org/apache/streampipes/service/base/rest/BaseResourceConfig.java
index 2233be263..7e5d1d77d 100644
--- a/streampipes-service-base/src/main/java/org/apache/streampipes/service/base/rest/BaseResourceConfig.java
+++ b/streampipes-service-base/src/main/java/org/apache/streampipes/service/base/rest/BaseResourceConfig.java
@@ -18,12 +18,14 @@
package org.apache.streampipes.service.base.rest;
import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.servlet.ServletProperties;
import java.util.List;
public abstract class BaseResourceConfig extends ResourceConfig {
public BaseResourceConfig() {
+ property(ServletProperties.FILTER_FORWARD_ON_404, true);
getClassesToRegister()
.forEach(set -> set.forEach(this::register));
register(ServiceHealthResource.class);
diff --git a/streampipes-backend/src/main/java/org/apache/streampipes/backend/UnauthorizedRequestEntryPoint.java b/streampipes-service-base/src/main/java/org/apache/streampipes/service/base/security/UnauthorizedRequestEntryPoint.java
similarity index 92%
rename from streampipes-backend/src/main/java/org/apache/streampipes/backend/UnauthorizedRequestEntryPoint.java
rename to streampipes-service-base/src/main/java/org/apache/streampipes/service/base/security/UnauthorizedRequestEntryPoint.java
index 181c178e3..91528c8ee 100644
--- a/streampipes-backend/src/main/java/org/apache/streampipes/backend/UnauthorizedRequestEntryPoint.java
+++ b/streampipes-service-base/src/main/java/org/apache/streampipes/service/base/security/UnauthorizedRequestEntryPoint.java
@@ -16,7 +16,7 @@
*
*/
-package org.apache.streampipes.backend;
+package org.apache.streampipes.service.base.security;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -33,7 +33,7 @@ public class UnauthorizedRequestEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException {
- LOG.error("Unauthorized request - {}", e.getMessage());
+ LOG.error("Unauthorized request to {}", httpServletRequest.getPathInfo());
httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, e.getLocalizedMessage());
}
diff --git a/streampipes-backend/src/main/java/org/apache/streampipes/backend/WebSecurityConfig.java b/streampipes-service-extensions-base/src/main/java/org/apache/streampipes/service/extensions/base/WebSecurityConfig.java
similarity index 50%
copy from streampipes-backend/src/main/java/org/apache/streampipes/backend/WebSecurityConfig.java
copy to streampipes-service-extensions-base/src/main/java/org/apache/streampipes/service/extensions/base/WebSecurityConfig.java
index e882c8ceb..ada8748ea 100644
--- a/streampipes-backend/src/main/java/org/apache/streampipes/backend/WebSecurityConfig.java
+++ b/streampipes-service-extensions-base/src/main/java/org/apache/streampipes/service/extensions/base/WebSecurityConfig.java
@@ -16,15 +16,16 @@
*
*/
-package org.apache.streampipes.backend;
+package org.apache.streampipes.service.extensions.base;
-import org.apache.streampipes.rest.filter.TokenAuthenticationFilter;
-import org.apache.streampipes.user.management.service.SpUserDetailsService;
+import org.apache.streampipes.commons.constants.Envs;
+import org.apache.streampipes.service.base.security.UnauthorizedRequestEntryPoint;
+import org.apache.streampipes.service.extensions.base.security.TokenAuthenticationFilter;
+import org.apache.streampipes.service.extensions.base.security.UnauthenticatedInterfaces;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import org.springframework.security.authentication.AuthenticationManager;
-import org.springframework.security.config.BeanIds;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
@@ -39,38 +40,56 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthentic
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
- private final UserDetailsService userDetailsService;
- private StreamPipesPasswordEncoder passwordEncoder;
+ private static final Logger LOG = LoggerFactory.getLogger(WebSecurityConfigurerAdapter.class);
+
+ public WebSecurityConfig() {
- public WebSecurityConfig(StreamPipesPasswordEncoder passwordEncoder) {
- this.passwordEncoder = passwordEncoder;
- this.userDetailsService = new SpUserDetailsService();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
- auth.userDetailsService(userDetailsService).passwordEncoder(this.passwordEncoder.passwordEncoder());
+ auth.userDetailsService(userDetailsService());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
- http
- .cors()
- .and()
- .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
- .and()
- .csrf().disable()
- .formLogin().disable()
- .httpBasic().disable()
- .exceptionHandling()
- .authenticationEntryPoint(new UnauthorizedRequestEntryPoint())
- .and()
- .authorizeRequests()
- .antMatchers(UnauthenticatedInterfaces.get().toArray(new String[0])).permitAll()
- .anyRequest()
- .authenticated().and()
- .addFilterBefore(tokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
+ if (isAnonymousAccess()) {
+ http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
+ .and()
+ .csrf().disable()
+ .formLogin().disable()
+ .httpBasic().disable().authorizeRequests().antMatchers("/**").permitAll();
+ } else {
+ http
+ .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
+ .and()
+ .csrf().disable()
+ .formLogin().disable()
+ .httpBasic().disable()
+ .exceptionHandling()
+ .authenticationEntryPoint(new UnauthorizedRequestEntryPoint())
+ .and()
+ .authorizeRequests()
+ .antMatchers(UnauthenticatedInterfaces.get().toArray(new String[0])).permitAll()
+ .anyRequest().authenticated().and().addFilterBefore(tokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
+ }
+ }
+
+ private boolean isAnonymousAccess() {
+ if (Envs.SP_EXT_AUTH_MODE.exists() && Envs.SP_EXT_AUTH_MODE.getValue().equals("AUTH")) {
+ if (Envs.SP_JWT_PUBLIC_KEY_LOC.exists()) {
+ LOG.info("Configured service for authenticated access mode");
+ return false;
+ } else {
+ LOG.warn("No env variable {} provided, which is required for authenticated access. Defaulting to anonymous access.",
+ Envs.SP_JWT_PUBLIC_KEY_LOC.getEnvVariableName());
+ return true;
+ }
+ } else {
+ LOG.info("Configured anonymous access for this service, consider providing an authentication option.");
+ return true;
+ }
}
public TokenAuthenticationFilter tokenAuthenticationFilter() {
@@ -79,13 +98,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
public UserDetailsService userDetailsService() {
- return userDetailsService;
- }
-
- @Bean(BeanIds.AUTHENTICATION_MANAGER)
- @Override
- public AuthenticationManager authenticationManagerBean() throws Exception {
- return super.authenticationManagerBean();
+ return username -> null;
}
}
diff --git a/streampipes-service-extensions-base/src/main/java/org/apache/streampipes/service/extensions/base/security/TokenAuthenticationFilter.java b/streampipes-service-extensions-base/src/main/java/org/apache/streampipes/service/extensions/base/security/TokenAuthenticationFilter.java
new file mode 100644
index 000000000..3b50f1c87
--- /dev/null
+++ b/streampipes-service-extensions-base/src/main/java/org/apache/streampipes/service/extensions/base/security/TokenAuthenticationFilter.java
@@ -0,0 +1,92 @@
+/*
+ * 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.apache.streampipes.service.extensions.base.security;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import io.jsonwebtoken.Claims;
+import org.apache.streampipes.commons.constants.HttpConstants;
+import org.apache.streampipes.model.UserInfo;
+import org.apache.streampipes.security.jwt.JwtTokenUtils;
+import org.apache.streampipes.security.jwt.JwtTokenValidator;
+import org.apache.streampipes.security.jwt.PublicKeyResolver;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
+import org.springframework.util.StringUtils;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+public class TokenAuthenticationFilter extends OncePerRequestFilter {
+
+
+ public TokenAuthenticationFilter() {
+ }
+
+ @Override
+ protected void doFilterInternal(HttpServletRequest request,
+ HttpServletResponse response,
+ FilterChain filterChain) throws ServletException, IOException {
+ try {
+ String jwt = getJwtFromRequest(request);
+ if (StringUtils.hasText(jwt) && JwtTokenValidator.validateJwtToken(jwt, new PublicKeyResolver())) {
+ Claims claims = JwtTokenUtils.getClaimsFromToken(jwt, new PublicKeyResolver());
+ applySuccessfulAuth(request, claims);
+ }
+ } catch (Exception ex) {
+ logger.error("Could not set user authentication in security context", ex);
+ }
+
+ filterChain.doFilter(request, response);
+ }
+
+ private String getJwtFromRequest(HttpServletRequest request) {
+ String bearerToken = request.getHeader(HttpConstants.AUTHORIZATION);
+ if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(HttpConstants.BEARER)) {
+ return bearerToken.substring(7);
+ }
+ return null;
+ }
+
+ private void applySuccessfulAuth(HttpServletRequest request,
+ Claims claims) throws JsonProcessingException {
+ UserInfo userInfo = parseUserInfo((Map<String, Object>) claims.get("user"));
+ UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userInfo, null, null);
+ authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
+
+ SecurityContextHolder.getContext().setAuthentication(authentication);
+ }
+
+ private UserInfo parseUserInfo(Map<String, Object> user) {
+ UserInfo userInfo = new UserInfo();
+ userInfo.setUsername(user.get("username").toString());
+ userInfo.setDisplayName(user.get("displayName").toString());
+ userInfo.setRoles(new HashSet<>((List<String>) user.get("roles")));
+
+ return userInfo;
+ }
+}
diff --git a/streampipes-service-base/src/main/java/org/apache/streampipes/service/base/rest/BaseResourceConfig.java b/streampipes-service-extensions-base/src/main/java/org/apache/streampipes/service/extensions/base/security/UnauthenticatedInterfaces.java
similarity index 66%
copy from streampipes-service-base/src/main/java/org/apache/streampipes/service/base/rest/BaseResourceConfig.java
copy to streampipes-service-extensions-base/src/main/java/org/apache/streampipes/service/extensions/base/security/UnauthenticatedInterfaces.java
index 2233be263..86e443ae4 100644
--- a/streampipes-service-base/src/main/java/org/apache/streampipes/service/base/rest/BaseResourceConfig.java
+++ b/streampipes-service-extensions-base/src/main/java/org/apache/streampipes/service/extensions/base/security/UnauthenticatedInterfaces.java
@@ -15,20 +15,24 @@
* limitations under the License.
*
*/
-package org.apache.streampipes.service.base.rest;
-import org.glassfish.jersey.server.ResourceConfig;
-import java.util.List;
+package org.apache.streampipes.service.extensions.base.security;
-public abstract class BaseResourceConfig extends ResourceConfig {
+import java.util.Arrays;
+import java.util.Collection;
- public BaseResourceConfig() {
- getClassesToRegister()
- .forEach(set -> set.forEach(this::register));
- register(ServiceHealthResource.class);
- }
- public abstract List<List<Class<?>>> getClassesToRegister();
+public class UnauthenticatedInterfaces {
+ public static Collection<String> get() {
+ return Arrays.asList(
+ "/svchealth/*",
+ "/",
+ "/sec/**",
+ "/sepa/**",
+ "/stream/**",
+ "/api/v1/worker/**"
+ );
+ }
}
diff --git a/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/util/UserInfoUtil.java b/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/util/UserInfoUtil.java
index 2cc2df172..2b4cd7d94 100644
--- a/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/util/UserInfoUtil.java
+++ b/streampipes-user-management/src/main/java/org/apache/streampipes/user/management/util/UserInfoUtil.java
@@ -19,7 +19,7 @@
package org.apache.streampipes.user.management.util;
import org.apache.streampipes.model.client.user.UserAccount;
-import org.apache.streampipes.model.client.user.UserInfo;
+import org.apache.streampipes.model.UserInfo;
import java.util.Set;
diff --git a/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model-client.ts b/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model-client.ts
index 279322215..ab4b1019b 100644
--- a/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model-client.ts
+++ b/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model-client.ts
@@ -18,7 +18,7 @@
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
-// Generated using typescript-generator version 2.27.744 on 2022-03-11 16:37:33.
+// Generated using typescript-generator version 2.27.744 on 2022-04-25 13:56:53.
export class ExtensionsServiceEndpointItem {
appId: string;
@@ -246,27 +246,6 @@ export class UserApiToken {
}
}
-export class UserInfo {
- darkMode: boolean;
- displayName: string;
- roles: string[];
- showTutorial: boolean;
- username: string;
-
- static fromData(data: UserInfo, target?: UserInfo): UserInfo {
- if (!data) {
- return data;
- }
- const instance = target || new UserInfo();
- instance.username = data.username;
- instance.displayName = data.displayName;
- instance.roles = __getCopyArrayFn(__identity<string>())(data.roles);
- instance.showTutorial = data.showTutorial;
- instance.darkMode = data.darkMode;
- return instance;
- }
-}
-
export type PrincipalType = "USER_ACCOUNT" | "SERVICE_ACCOUNT" | "GROUP";
export type Privilege = "PRIVILEGE_READ_PIPELINE" | "PRIVILEGE_WRITE_PIPELINE" | "PRIVILEGE_DELETE_PIPELINE" | "PRIVILEGE_READ_ADAPTER" | "PRIVILEGE_WRITE_ADAPTER" | "PRIVILEGE_DELETE_ADAPTER" | "PRIVILEGE_READ_PIPELINE_ELEMENT" | "PRIVILEGE_WRITE_PIPELINE_ELEMENT" | "PRIVILEGE_DELETE_PIPELINE_ELEMENT" | "PRIVILEGE_READ_DASHBOARD" | "PRIVILEGE_WRITE_DASHBOARD" | "PRIVILEGE_DELETE_DASHBOARD" | "PRIVILEGE_READ_DASHBOARD_WIDGET" | "PRIVILEGE_WRITE_DASHBOARD_WIDGET" | "PRIVILEGE_DELETE_DASHB [...]
diff --git a/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts b/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
index 18a564910..393aa4c56 100644
--- a/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
+++ b/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
@@ -18,7 +18,7 @@
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
-// Generated using typescript-generator version 2.27.744 on 2022-03-11 16:37:20.
+// Generated using typescript-generator version 2.27.744 on 2022-04-25 13:56:39.
export class AbstractStreamPipesEntity {
"@class": "org.apache.streampipes.model.base.AbstractStreamPipesEntity" | "org.apache.streampipes.model.base.NamedStreamPipesEntity" | "org.apache.streampipes.model.connect.adapter.AdapterDescription" | "org.apache.streampipes.model.connect.adapter.AdapterSetDescription" | "org.apache.streampipes.model.connect.adapter.GenericAdapterSetDescription" | "org.apache.streampipes.model.connect.adapter.SpecificAdapterSetDescription" | "org.apache.streampipes.model.connect.adapter.AdapterStre [...]
@@ -151,8 +151,8 @@ export class NamedStreamPipesEntity extends AbstractStreamPipesEntity {
instance.applicationLinks = __getCopyArrayFn(ApplicationLink.fromData)(data.applicationLinks);
instance.internallyManaged = data.internallyManaged;
instance.connectedTo = __getCopyArrayFn(__identity<string>())(data.connectedTo);
- instance.dom = data.dom;
instance.uri = data.uri;
+ instance.dom = data.dom;
instance._rev = data._rev;
return instance;
}
@@ -192,8 +192,8 @@ export class AdapterDescription extends NamedStreamPipesEntity {
instance.selectedEndpointUrl = data.selectedEndpointUrl;
instance.correspondingServiceGroup = data.correspondingServiceGroup;
instance.correspondingDataStreamElementId = data.correspondingDataStreamElementId;
- instance.streamRules = __getCopyArrayFn(__identity<any>())(data.streamRules);
instance.valueRules = __getCopyArrayFn(__identity<any>())(data.valueRules);
+ instance.streamRules = __getCopyArrayFn(__identity<any>())(data.streamRules);
instance.schemaRules = __getCopyArrayFn(__identity<any>())(data.schemaRules);
return instance;
}
@@ -2500,8 +2500,8 @@ export class PipelineTemplateDescription extends NamedStreamPipesEntity {
const instance = target || new PipelineTemplateDescription();
super.fromData(data, instance);
instance.boundTo = __getCopyArrayFn(BoundPipelineElement.fromData)(data.boundTo);
- instance.pipelineTemplateDescription = data.pipelineTemplateDescription;
instance.pipelineTemplateName = data.pipelineTemplateName;
+ instance.pipelineTemplateDescription = data.pipelineTemplateDescription;
instance.pipelineTemplateId = data.pipelineTemplateId;
return instance;
}
@@ -3165,6 +3165,27 @@ export class UserDefinedOutputStrategy extends OutputStrategy {
}
}
+export class UserInfo {
+ darkMode: boolean;
+ displayName: string;
+ roles: string[];
+ showTutorial: boolean;
+ username: string;
+
+ static fromData(data: UserInfo, target?: UserInfo): UserInfo {
+ if (!data) {
+ return data;
+ }
+ const instance = target || new UserInfo();
+ instance.username = data.username;
+ instance.displayName = data.displayName;
+ instance.roles = __getCopyArrayFn(__identity<string>())(data.roles);
+ instance.showTutorial = data.showTutorial;
+ instance.darkMode = data.darkMode;
+ return instance;
+ }
+}
+
export class VisualizablePipeline {
pipelineId: string;
pipelineName: string;