Remove Java security context serialization (#2677)
Remove Java security context serialization - it is replaced by JSON security context serialization (optimized as size). Backward incompatible change. Java security context serialization was not used in default hawkbit runtime out of the box. So, it's assumed none uses it. Anyway, if anyone has enabled it, he could, in order to keep backward compatibility, get the java security context serialization from the previous hawkbit releases/commits and register it again as a spring bean in his hawkbit extension. Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
@@ -65,11 +65,12 @@ public class SecurityAutoConfiguration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@link ContextAware} (hence {@link TenantAware}) bean based on the given {@link UserAuthoritiesResolver} and
|
* Creates a {@link ContextAware} (hence {@link TenantAware}) bean based on the given {@link UserAuthoritiesResolver},
|
||||||
* {@link SecurityContextSerializer}.
|
* {@link SecurityContextSerializer} and {@link TenantResolver}.
|
||||||
*
|
*
|
||||||
* @param authoritiesResolver The user authorities/roles resolver
|
* @param authoritiesResolver The user authorities/roles resolver
|
||||||
* @param securityContextSerializer The security context serializer.
|
* @param securityContextSerializer The security context serializer (optional, if not found the default {@link SecurityContextSerializer#NOP} is used).
|
||||||
|
* @param tenantResolver The tenant resolver (optional, if not found the default {@link DefaultTenantResolver} is used).
|
||||||
* @return the {@link ContextAware} singleton bean.
|
* @return the {@link ContextAware} singleton bean.
|
||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
|
|||||||
@@ -10,15 +10,16 @@
|
|||||||
package org.eclipse.hawkbit.security.controller;
|
package org.eclipse.hawkbit.security.controller;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.eclipse.hawkbit.security.controller.GatewayTokenAuthenticator.GATEWAY_SECURITY_TOKEN_AUTH_SCHEME;
|
||||||
|
import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_ENABLED;
|
||||||
|
import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||||
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
|
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
|
||||||
import org.eclipse.hawkbit.security.SecurityContextSerializer;
|
|
||||||
import org.eclipse.hawkbit.security.SecurityContextTenantAware;
|
import org.eclipse.hawkbit.security.SecurityContextTenantAware;
|
||||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||||
import org.eclipse.hawkbit.tenancy.UserAuthoritiesResolver;
|
import org.eclipse.hawkbit.tenancy.UserAuthoritiesResolver;
|
||||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
@@ -32,7 +33,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
|
|||||||
@ExtendWith(MockitoExtension.class)
|
@ExtendWith(MockitoExtension.class)
|
||||||
class GatewayTokenAuthenticatorTest {
|
class GatewayTokenAuthenticatorTest {
|
||||||
|
|
||||||
private static final String CONTROLLER_ID = "controllerId_gwtoken";
|
private static final String CONTROLLER_ID = "controllerId_gwToken";
|
||||||
private static final String GATEWAY_TOKEN = "test-gw-token";
|
private static final String GATEWAY_TOKEN = "test-gw-token";
|
||||||
private static final String UNKNOWN_TOKEN = "unknown";
|
private static final String UNKNOWN_TOKEN = "unknown";
|
||||||
|
|
||||||
@@ -49,15 +50,11 @@ class GatewayTokenAuthenticatorTest {
|
|||||||
private TenantConfigurationManagement tenantConfigurationManagementMock;
|
private TenantConfigurationManagement tenantConfigurationManagementMock;
|
||||||
@Mock
|
@Mock
|
||||||
private UserAuthoritiesResolver authoritiesResolver;
|
private UserAuthoritiesResolver authoritiesResolver;
|
||||||
@Mock
|
|
||||||
private SecurityContextSerializer securityContextSerializer;
|
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void before() {
|
void before() {
|
||||||
final SecurityContextTenantAware tenantAware = new SecurityContextTenantAware(authoritiesResolver, securityContextSerializer);
|
final SecurityContextTenantAware tenantAware = new SecurityContextTenantAware(authoritiesResolver);
|
||||||
authenticator = new GatewayTokenAuthenticator(
|
authenticator = new GatewayTokenAuthenticator(tenantConfigurationManagementMock, tenantAware, new SystemSecurityContext(tenantAware));
|
||||||
tenantConfigurationManagementMock, tenantAware,
|
|
||||||
new SystemSecurityContext(tenantAware));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -66,11 +63,9 @@ class GatewayTokenAuthenticatorTest {
|
|||||||
@Test
|
@Test
|
||||||
void testWithGwToken() {
|
void testWithGwToken() {
|
||||||
final ControllerSecurityToken securityToken = prepareSecurityToken(GATEWAY_TOKEN);
|
final ControllerSecurityToken securityToken = prepareSecurityToken(GATEWAY_TOKEN);
|
||||||
when(tenantConfigurationManagementMock.getConfigurationValue(
|
when(tenantConfigurationManagementMock.getConfigurationValue(AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY, String.class))
|
||||||
TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY, String.class))
|
|
||||||
.thenReturn(CONFIG_VALUE_GW_TOKEN);
|
.thenReturn(CONFIG_VALUE_GW_TOKEN);
|
||||||
when(tenantConfigurationManagementMock.getConfigurationValue(
|
when(tenantConfigurationManagementMock.getConfigurationValue(AUTHENTICATION_GATEWAY_SECURITY_TOKEN_ENABLED, Boolean.class))
|
||||||
TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_ENABLED, Boolean.class))
|
|
||||||
.thenReturn(CONFIG_VALUE_ENABLED);
|
.thenReturn(CONFIG_VALUE_ENABLED);
|
||||||
|
|
||||||
assertThat(authenticator.authenticate(securityToken))
|
assertThat(authenticator.authenticate(securityToken))
|
||||||
@@ -84,11 +79,9 @@ class GatewayTokenAuthenticatorTest {
|
|||||||
@Test
|
@Test
|
||||||
void testWithBadGwToken() {
|
void testWithBadGwToken() {
|
||||||
final ControllerSecurityToken securityToken = prepareSecurityToken(UNKNOWN_TOKEN);
|
final ControllerSecurityToken securityToken = prepareSecurityToken(UNKNOWN_TOKEN);
|
||||||
when(tenantConfigurationManagementMock.getConfigurationValue(
|
when(tenantConfigurationManagementMock.getConfigurationValue(AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY, String.class))
|
||||||
TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY, String.class))
|
|
||||||
.thenReturn(CONFIG_VALUE_GW_TOKEN);
|
.thenReturn(CONFIG_VALUE_GW_TOKEN);
|
||||||
when(tenantConfigurationManagementMock.getConfigurationValue(
|
when(tenantConfigurationManagementMock.getConfigurationValue(AUTHENTICATION_GATEWAY_SECURITY_TOKEN_ENABLED, Boolean.class))
|
||||||
TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_ENABLED, Boolean.class))
|
|
||||||
.thenReturn(CONFIG_VALUE_ENABLED);
|
.thenReturn(CONFIG_VALUE_ENABLED);
|
||||||
|
|
||||||
assertThat(authenticator.authenticate(securityToken)).isNull();
|
assertThat(authenticator.authenticate(securityToken)).isNull();
|
||||||
@@ -108,8 +101,7 @@ class GatewayTokenAuthenticatorTest {
|
|||||||
@Test
|
@Test
|
||||||
void testWithGwTokenButDisabled() {
|
void testWithGwTokenButDisabled() {
|
||||||
final ControllerSecurityToken securityToken = prepareSecurityToken(GATEWAY_TOKEN);
|
final ControllerSecurityToken securityToken = prepareSecurityToken(GATEWAY_TOKEN);
|
||||||
when(tenantConfigurationManagementMock.getConfigurationValue(
|
when(tenantConfigurationManagementMock.getConfigurationValue(AUTHENTICATION_GATEWAY_SECURITY_TOKEN_ENABLED, Boolean.class))
|
||||||
TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_ENABLED, Boolean.class))
|
|
||||||
.thenReturn(CONFIG_VALUE_DISABLED);
|
.thenReturn(CONFIG_VALUE_DISABLED);
|
||||||
|
|
||||||
assertThat(authenticator.authenticate(securityToken)).isNull();
|
assertThat(authenticator.authenticate(securityToken)).isNull();
|
||||||
@@ -117,7 +109,7 @@ class GatewayTokenAuthenticatorTest {
|
|||||||
|
|
||||||
private static ControllerSecurityToken prepareSecurityToken(final String gwToken) {
|
private static ControllerSecurityToken prepareSecurityToken(final String gwToken) {
|
||||||
final ControllerSecurityToken securityToken = new ControllerSecurityToken("DEFAULT", CONTROLLER_ID);
|
final ControllerSecurityToken securityToken = new ControllerSecurityToken("DEFAULT", CONTROLLER_ID);
|
||||||
securityToken.putHeader(ControllerSecurityToken.AUTHORIZATION_HEADER, GatewayTokenAuthenticator.GATEWAY_SECURITY_TOKEN_AUTH_SCHEME + gwToken);
|
securityToken.putHeader(ControllerSecurityToken.AUTHORIZATION_HEADER, GATEWAY_SECURITY_TOKEN_AUTH_SCHEME + gwToken);
|
||||||
return securityToken;
|
return securityToken;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,15 +10,15 @@
|
|||||||
package org.eclipse.hawkbit.security.controller;
|
package org.eclipse.hawkbit.security.controller;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.AUTHENTICATION_HEADER_AUTHORITY_NAME;
|
||||||
|
import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.AUTHENTICATION_HEADER_ENABLED;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||||
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
|
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
|
||||||
import org.eclipse.hawkbit.security.SecurityContextSerializer;
|
|
||||||
import org.eclipse.hawkbit.security.SecurityContextTenantAware;
|
import org.eclipse.hawkbit.security.SecurityContextTenantAware;
|
||||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||||
import org.eclipse.hawkbit.tenancy.UserAuthoritiesResolver;
|
import org.eclipse.hawkbit.tenancy.UserAuthoritiesResolver;
|
||||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
@@ -59,12 +59,10 @@ class SecurityHeaderAuthenticatorTest {
|
|||||||
private TenantConfigurationManagement tenantConfigurationManagementMock;
|
private TenantConfigurationManagement tenantConfigurationManagementMock;
|
||||||
@Mock
|
@Mock
|
||||||
private UserAuthoritiesResolver authoritiesResolver;
|
private UserAuthoritiesResolver authoritiesResolver;
|
||||||
@Mock
|
|
||||||
private SecurityContextSerializer securityContextSerializer;
|
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void before() {
|
void before() {
|
||||||
final SecurityContextTenantAware tenantAware = new SecurityContextTenantAware(authoritiesResolver, securityContextSerializer);
|
final SecurityContextTenantAware tenantAware = new SecurityContextTenantAware(authoritiesResolver);
|
||||||
authenticator = new SecurityHeaderAuthenticator(
|
authenticator = new SecurityHeaderAuthenticator(
|
||||||
tenantConfigurationManagementMock, tenantAware,
|
tenantConfigurationManagementMock, tenantAware,
|
||||||
new SystemSecurityContext(tenantAware), CA_COMMON_NAME, "X-Ssl-Issuer-Hash-%d"
|
new SystemSecurityContext(tenantAware), CA_COMMON_NAME, "X-Ssl-Issuer-Hash-%d"
|
||||||
@@ -77,11 +75,9 @@ class SecurityHeaderAuthenticatorTest {
|
|||||||
@Test
|
@Test
|
||||||
void testWithSingleKnownHash() {
|
void testWithSingleKnownHash() {
|
||||||
final ControllerSecurityToken securityToken = prepareSecurityToken(SINGLE_HASH);
|
final ControllerSecurityToken securityToken = prepareSecurityToken(SINGLE_HASH);
|
||||||
when(tenantConfigurationManagementMock.getConfigurationValue(
|
when(tenantConfigurationManagementMock.getConfigurationValue(AUTHENTICATION_HEADER_AUTHORITY_NAME, String.class))
|
||||||
TenantConfigurationKey.AUTHENTICATION_HEADER_AUTHORITY_NAME, String.class))
|
|
||||||
.thenReturn(CONFIG_VALUE_SINGLE_HASH);
|
.thenReturn(CONFIG_VALUE_SINGLE_HASH);
|
||||||
when(tenantConfigurationManagementMock.getConfigurationValue(
|
when(tenantConfigurationManagementMock.getConfigurationValue(AUTHENTICATION_HEADER_ENABLED, Boolean.class))
|
||||||
TenantConfigurationKey.AUTHENTICATION_HEADER_ENABLED, Boolean.class))
|
|
||||||
.thenReturn(CONFIG_VALUE_ENABLED);
|
.thenReturn(CONFIG_VALUE_ENABLED);
|
||||||
|
|
||||||
assertThat(authenticator.authenticate(securityToken))
|
assertThat(authenticator.authenticate(securityToken))
|
||||||
@@ -94,11 +90,9 @@ class SecurityHeaderAuthenticatorTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
void testWithMultipleKnownHashes() {
|
void testWithMultipleKnownHashes() {
|
||||||
when(tenantConfigurationManagementMock.getConfigurationValue(
|
when(tenantConfigurationManagementMock.getConfigurationValue(AUTHENTICATION_HEADER_AUTHORITY_NAME, String.class))
|
||||||
TenantConfigurationKey.AUTHENTICATION_HEADER_AUTHORITY_NAME, String.class))
|
|
||||||
.thenReturn(CONFIG_VALUE_MULTI_HASH);
|
.thenReturn(CONFIG_VALUE_MULTI_HASH);
|
||||||
when(tenantConfigurationManagementMock.getConfigurationValue(
|
when(tenantConfigurationManagementMock.getConfigurationValue(AUTHENTICATION_HEADER_ENABLED, Boolean.class))
|
||||||
TenantConfigurationKey.AUTHENTICATION_HEADER_ENABLED, Boolean.class))
|
|
||||||
.thenReturn(CONFIG_VALUE_ENABLED);
|
.thenReturn(CONFIG_VALUE_ENABLED);
|
||||||
|
|
||||||
assertThat(authenticator.authenticate(prepareSecurityToken(SINGLE_HASH)))
|
assertThat(authenticator.authenticate(prepareSecurityToken(SINGLE_HASH)))
|
||||||
@@ -118,11 +112,9 @@ class SecurityHeaderAuthenticatorTest {
|
|||||||
@Test
|
@Test
|
||||||
void testWithUnknownHash() {
|
void testWithUnknownHash() {
|
||||||
final ControllerSecurityToken securityToken = prepareSecurityToken(UNKNOWN_HASH);
|
final ControllerSecurityToken securityToken = prepareSecurityToken(UNKNOWN_HASH);
|
||||||
when(tenantConfigurationManagementMock.getConfigurationValue(
|
when(tenantConfigurationManagementMock.getConfigurationValue(AUTHENTICATION_HEADER_AUTHORITY_NAME, String.class))
|
||||||
TenantConfigurationKey.AUTHENTICATION_HEADER_AUTHORITY_NAME, String.class))
|
|
||||||
.thenReturn(CONFIG_VALUE_MULTI_HASH);
|
.thenReturn(CONFIG_VALUE_MULTI_HASH);
|
||||||
when(tenantConfigurationManagementMock.getConfigurationValue(
|
when(tenantConfigurationManagementMock.getConfigurationValue(AUTHENTICATION_HEADER_ENABLED, Boolean.class))
|
||||||
TenantConfigurationKey.AUTHENTICATION_HEADER_ENABLED, Boolean.class))
|
|
||||||
.thenReturn(CONFIG_VALUE_ENABLED);
|
.thenReturn(CONFIG_VALUE_ENABLED);
|
||||||
|
|
||||||
assertThat(authenticator.authenticate(securityToken)).isNull();
|
assertThat(authenticator.authenticate(securityToken)).isNull();
|
||||||
@@ -154,8 +146,7 @@ class SecurityHeaderAuthenticatorTest {
|
|||||||
@Test
|
@Test
|
||||||
void testWithSingleKnownHashButDisabled() {
|
void testWithSingleKnownHashButDisabled() {
|
||||||
final ControllerSecurityToken securityToken = prepareSecurityToken(SINGLE_HASH);
|
final ControllerSecurityToken securityToken = prepareSecurityToken(SINGLE_HASH);
|
||||||
when(tenantConfigurationManagementMock.getConfigurationValue(
|
when(tenantConfigurationManagementMock.getConfigurationValue(AUTHENTICATION_HEADER_ENABLED, Boolean.class))
|
||||||
TenantConfigurationKey.AUTHENTICATION_HEADER_ENABLED, Boolean.class))
|
|
||||||
.thenReturn(CONFIG_VALUE_DISABLED);
|
.thenReturn(CONFIG_VALUE_DISABLED);
|
||||||
|
|
||||||
assertThat(authenticator.authenticate(securityToken)).isNull();
|
assertThat(authenticator.authenticate(securityToken)).isNull();
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
package org.eclipse.hawkbit.security.controller;
|
package org.eclipse.hawkbit.security.controller;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.AUTHENTICATION_TARGET_SECURITY_TOKEN_ENABLED;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@@ -18,11 +19,9 @@ import org.eclipse.hawkbit.repository.ControllerManagement;
|
|||||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||||
import org.eclipse.hawkbit.repository.model.Target;
|
import org.eclipse.hawkbit.repository.model.Target;
|
||||||
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
|
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
|
||||||
import org.eclipse.hawkbit.security.SecurityContextSerializer;
|
|
||||||
import org.eclipse.hawkbit.security.SecurityContextTenantAware;
|
import org.eclipse.hawkbit.security.SecurityContextTenantAware;
|
||||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||||
import org.eclipse.hawkbit.tenancy.UserAuthoritiesResolver;
|
import org.eclipse.hawkbit.tenancy.UserAuthoritiesResolver;
|
||||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
@@ -37,7 +36,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
|
|||||||
@ExtendWith(MockitoExtension.class)
|
@ExtendWith(MockitoExtension.class)
|
||||||
class SecurityTokenAuthenticatorTest {
|
class SecurityTokenAuthenticatorTest {
|
||||||
|
|
||||||
private static final String CONTROLLER_ID = "controllerId_gwtoken";
|
private static final String CONTROLLER_ID = "controllerId_token";
|
||||||
private static final String SECURITY_TOKEN = "test-sec-token";
|
private static final String SECURITY_TOKEN = "test-sec-token";
|
||||||
private static final String UNKNOWN_TOKEN = "unknown";
|
private static final String UNKNOWN_TOKEN = "unknown";
|
||||||
|
|
||||||
@@ -54,12 +53,10 @@ class SecurityTokenAuthenticatorTest {
|
|||||||
private ControllerManagement controllerManagementMock;
|
private ControllerManagement controllerManagementMock;
|
||||||
@Mock
|
@Mock
|
||||||
private UserAuthoritiesResolver authoritiesResolver;
|
private UserAuthoritiesResolver authoritiesResolver;
|
||||||
@Mock
|
|
||||||
private SecurityContextSerializer securityContextSerializer;
|
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void before() {
|
void before() {
|
||||||
final SecurityContextTenantAware tenantAware = new SecurityContextTenantAware(authoritiesResolver, securityContextSerializer);
|
final SecurityContextTenantAware tenantAware = new SecurityContextTenantAware(authoritiesResolver);
|
||||||
authenticator = new SecurityTokenAuthenticator(
|
authenticator = new SecurityTokenAuthenticator(
|
||||||
tenantConfigurationManagementMock, tenantAware,
|
tenantConfigurationManagementMock, tenantAware,
|
||||||
new SystemSecurityContext(tenantAware), controllerManagementMock);
|
new SystemSecurityContext(tenantAware), controllerManagementMock);
|
||||||
@@ -71,8 +68,7 @@ class SecurityTokenAuthenticatorTest {
|
|||||||
@Test
|
@Test
|
||||||
void testWithSecToken() {
|
void testWithSecToken() {
|
||||||
final ControllerSecurityToken securityToken = prepareSecurityToken(SECURITY_TOKEN);
|
final ControllerSecurityToken securityToken = prepareSecurityToken(SECURITY_TOKEN);
|
||||||
when(tenantConfigurationManagementMock.getConfigurationValue(
|
when(tenantConfigurationManagementMock.getConfigurationValue(AUTHENTICATION_TARGET_SECURITY_TOKEN_ENABLED, Boolean.class))
|
||||||
TenantConfigurationKey.AUTHENTICATION_TARGET_SECURITY_TOKEN_ENABLED, Boolean.class))
|
|
||||||
.thenReturn(CONFIG_VALUE_ENABLED);
|
.thenReturn(CONFIG_VALUE_ENABLED);
|
||||||
|
|
||||||
final Target target = Mockito.mock(Target.class);
|
final Target target = Mockito.mock(Target.class);
|
||||||
@@ -91,8 +87,7 @@ class SecurityTokenAuthenticatorTest {
|
|||||||
@Test
|
@Test
|
||||||
void testWithBadSecToken() {
|
void testWithBadSecToken() {
|
||||||
final ControllerSecurityToken securityToken = prepareSecurityToken(UNKNOWN_TOKEN);
|
final ControllerSecurityToken securityToken = prepareSecurityToken(UNKNOWN_TOKEN);
|
||||||
when(tenantConfigurationManagementMock.getConfigurationValue(
|
when(tenantConfigurationManagementMock.getConfigurationValue(AUTHENTICATION_TARGET_SECURITY_TOKEN_ENABLED, Boolean.class))
|
||||||
TenantConfigurationKey.AUTHENTICATION_TARGET_SECURITY_TOKEN_ENABLED, Boolean.class))
|
|
||||||
.thenReturn(CONFIG_VALUE_ENABLED);
|
.thenReturn(CONFIG_VALUE_ENABLED);
|
||||||
|
|
||||||
assertThat(authenticator.authenticate(securityToken)).isNull();
|
assertThat(authenticator.authenticate(securityToken)).isNull();
|
||||||
@@ -112,8 +107,7 @@ class SecurityTokenAuthenticatorTest {
|
|||||||
@Test
|
@Test
|
||||||
void testWithSecTokenButDisabled() {
|
void testWithSecTokenButDisabled() {
|
||||||
final ControllerSecurityToken securityToken = prepareSecurityToken(SECURITY_TOKEN);
|
final ControllerSecurityToken securityToken = prepareSecurityToken(SECURITY_TOKEN);
|
||||||
when(tenantConfigurationManagementMock.getConfigurationValue(
|
when(tenantConfigurationManagementMock.getConfigurationValue(AUTHENTICATION_TARGET_SECURITY_TOKEN_ENABLED, Boolean.class))
|
||||||
TenantConfigurationKey.AUTHENTICATION_TARGET_SECURITY_TOKEN_ENABLED, Boolean.class))
|
|
||||||
.thenReturn(CONFIG_VALUE_DISABLED);
|
.thenReturn(CONFIG_VALUE_DISABLED);
|
||||||
|
|
||||||
assertThat(authenticator.authenticate(securityToken)).isNull();
|
assertThat(authenticator.authenticate(securityToken)).isNull();
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ import org.eclipse.hawkbit.repository.model.ActionProperties;
|
|||||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
import org.eclipse.hawkbit.repository.model.Target;
|
import org.eclipse.hawkbit.repository.model.Target;
|
||||||
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
|
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
|
||||||
import org.eclipse.hawkbit.security.SecurityContextSerializer;
|
|
||||||
import org.eclipse.hawkbit.security.SecurityContextTenantAware;
|
import org.eclipse.hawkbit.security.SecurityContextTenantAware;
|
||||||
import org.eclipse.hawkbit.security.SecurityTokenGenerator;
|
import org.eclipse.hawkbit.security.SecurityTokenGenerator;
|
||||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||||
@@ -96,8 +95,6 @@ class AmqpMessageHandlerServiceTest {
|
|||||||
private RabbitTemplate rabbitTemplate;
|
private RabbitTemplate rabbitTemplate;
|
||||||
@Mock
|
@Mock
|
||||||
private UserAuthoritiesResolver authoritiesResolver;
|
private UserAuthoritiesResolver authoritiesResolver;
|
||||||
@Mock
|
|
||||||
private SecurityContextSerializer securityContextSerializer;
|
|
||||||
|
|
||||||
@Captor
|
@Captor
|
||||||
private ArgumentCaptor<Map<String, String>> attributesCaptor;
|
private ArgumentCaptor<Map<String, String>> attributesCaptor;
|
||||||
@@ -126,7 +123,7 @@ class AmqpMessageHandlerServiceTest {
|
|||||||
lenient().when(tenantConfigurationManagement.getConfigurationValue(MULTI_ASSIGNMENTS_ENABLED, Boolean.class))
|
lenient().when(tenantConfigurationManagement.getConfigurationValue(MULTI_ASSIGNMENTS_ENABLED, Boolean.class))
|
||||||
.thenReturn(multiAssignmentConfig);
|
.thenReturn(multiAssignmentConfig);
|
||||||
|
|
||||||
final SecurityContextTenantAware tenantAware = new SecurityContextTenantAware(authoritiesResolver, securityContextSerializer);
|
final SecurityContextTenantAware tenantAware = new SecurityContextTenantAware(authoritiesResolver);
|
||||||
final SystemSecurityContext systemSecurityContext = new SystemSecurityContext(tenantAware);
|
final SystemSecurityContext systemSecurityContext = new SystemSecurityContext(tenantAware);
|
||||||
|
|
||||||
amqpMessageHandlerService = new AmqpMessageHandlerService(rabbitTemplate, amqpMessageDispatcherServiceMock,
|
amqpMessageHandlerService = new AmqpMessageHandlerService(rabbitTemplate, amqpMessageDispatcherServiceMock,
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Contributors to the Eclipse Foundation
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made
|
||||||
|
* available under the terms of the Eclipse Public License 2.0
|
||||||
|
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.eclipse.hawkbit.repository.jpa.acm;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.security.SecurityContextSerializer;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
class AcmTestConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
SecurityContextSerializer securityContextSerializer() {
|
||||||
|
return SecurityContextSerializer.JSON_SERIALIZATION;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -37,11 +37,13 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticatio
|
|||||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
import org.springframework.security.core.context.SecurityContext;
|
import org.springframework.security.core.context.SecurityContext;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Feature: Component Tests - Context runner<br/>
|
* Feature: Component Tests - Context runner<br/>
|
||||||
* Story: Test Context Runner
|
* Story: Test Context Runner
|
||||||
*/
|
*/
|
||||||
|
@ContextConfiguration(classes = { AcmTestConfiguration.class })
|
||||||
class ContextAwareTest extends AbstractJpaIntegrationTest {
|
class ContextAwareTest extends AbstractJpaIntegrationTest {
|
||||||
|
|
||||||
private static final List<String> AUTHORITIES = SpPermission.getAllAuthorities();
|
private static final List<String> AUTHORITIES = SpPermission.getAllAuthorities();
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ import org.springframework.test.context.ContextConfiguration;
|
|||||||
* Feature: Component Tests - Access Control<br/>
|
* Feature: Component Tests - Access Control<br/>
|
||||||
* Story: Test Target Access Controller
|
* Story: Test Target Access Controller
|
||||||
*/
|
*/
|
||||||
@ContextConfiguration(classes = { DefaultAccessControllerConfiguration.class })
|
@ContextConfiguration(classes = { DefaultAccessControllerConfiguration.class, AcmTestConfiguration.class })
|
||||||
class TargetAccessControllerTest extends AbstractJpaIntegrationTest {
|
class TargetAccessControllerTest extends AbstractJpaIntegrationTest {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ import org.eclipse.hawkbit.tenancy.configuration.ControllerPollProperties;
|
|||||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties;
|
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties;
|
||||||
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
|
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
|
||||||
import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler;
|
import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.cache.caffeine.CaffeineCacheManager;
|
import org.springframework.cache.caffeine.CaffeineCacheManager;
|
||||||
@@ -144,11 +145,6 @@ public class TestConfiguration implements AsyncConfigurer {
|
|||||||
return (tenant, username) -> Collections.emptyList();
|
return (tenant, username) -> Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
|
||||||
SecurityContextSerializer securityContextSerializer() {
|
|
||||||
return SecurityContextSerializer.JSON_SERIALIZATION;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
TenantResolver tenantResolver() {
|
TenantResolver tenantResolver() {
|
||||||
return new DefaultTenantResolver();
|
return new DefaultTenantResolver();
|
||||||
@@ -156,7 +152,8 @@ public class TestConfiguration implements AsyncConfigurer {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
ContextAware contextAware(
|
ContextAware contextAware(
|
||||||
final UserAuthoritiesResolver authoritiesResolver, final SecurityContextSerializer securityContextSerializer,
|
final UserAuthoritiesResolver authoritiesResolver,
|
||||||
|
@Autowired(required = false) final SecurityContextSerializer securityContextSerializer,
|
||||||
final TenantResolver tenantResolver) {
|
final TenantResolver tenantResolver) {
|
||||||
// allow spying the security context
|
// allow spying the security context
|
||||||
return org.mockito.Mockito.spy(new SecurityContextTenantAware(authoritiesResolver, securityContextSerializer, tenantResolver));
|
return org.mockito.Mockito.spy(new SecurityContextTenantAware(authoritiesResolver, securityContextSerializer, tenantResolver));
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ import org.eclipse.hawkbit.security.SpringSecurityAuditorAware.AuditorAwarePrinc
|
|||||||
import org.eclipse.hawkbit.tenancy.TenantAwareAuthenticationDetails;
|
import org.eclipse.hawkbit.tenancy.TenantAwareAuthenticationDetails;
|
||||||
import org.eclipse.hawkbit.tenancy.TenantAwareUser;
|
import org.eclipse.hawkbit.tenancy.TenantAwareUser;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.AuthenticationException;
|
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
import org.springframework.security.core.context.SecurityContext;
|
import org.springframework.security.core.context.SecurityContext;
|
||||||
@@ -49,17 +48,8 @@ public interface SecurityContextSerializer {
|
|||||||
SecurityContextSerializer NOP = new Nop();
|
SecurityContextSerializer NOP = new Nop();
|
||||||
/**
|
/**
|
||||||
* Serializer the uses JSON serialization.
|
* Serializer the uses JSON serialization.
|
||||||
* <p/>
|
|
||||||
* Note that on deserialization this serialization does (if configured) fallback to {@link #JAVA_SERIALIZATION}.
|
|
||||||
*/
|
*/
|
||||||
SecurityContextSerializer JSON_SERIALIZATION = new JsonSerialization();
|
SecurityContextSerializer JSON_SERIALIZATION = new JsonSerialization();
|
||||||
/**
|
|
||||||
* Serializer the uses Java serialization of {@link java.io.Serializable} objects (legacy, not recommended).
|
|
||||||
* <p/>
|
|
||||||
* Note that serialized via java serialization context might become unreadable if incompatible
|
|
||||||
* changes are made to the object classes.
|
|
||||||
*/
|
|
||||||
SecurityContextSerializer JAVA_SERIALIZATION = new JavaSerialization();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return security context as string (could be just a reference)
|
* Return security context as string (could be just a reference)
|
||||||
@@ -82,11 +72,9 @@ public interface SecurityContextSerializer {
|
|||||||
* It returns <code>null</code> as serialized context and throws exception if
|
* It returns <code>null</code> as serialized context and throws exception if
|
||||||
* someone try to deserialize anything.
|
* someone try to deserialize anything.
|
||||||
*/
|
*/
|
||||||
|
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
class Nop implements SecurityContextSerializer {
|
class Nop implements SecurityContextSerializer {
|
||||||
|
|
||||||
private Nop() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String serialize(final SecurityContext securityContext) {
|
public String serialize(final SecurityContext securityContext) {
|
||||||
return null;
|
return null;
|
||||||
@@ -106,8 +94,6 @@ public interface SecurityContextSerializer {
|
|||||||
class JsonSerialization implements SecurityContextSerializer {
|
class JsonSerialization implements SecurityContextSerializer {
|
||||||
|
|
||||||
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||||
private static final boolean FALLBACK_TO_JAVA_SERIALIZATION =
|
|
||||||
!Boolean.getBoolean("hawkbit.security.contextSerializer.json.no-fallback-to-java");
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String serialize(final SecurityContext securityContext) {
|
public String serialize(final SecurityContext securityContext) {
|
||||||
@@ -124,13 +110,6 @@ public interface SecurityContextSerializer {
|
|||||||
Objects.requireNonNull(securityContextString);
|
Objects.requireNonNull(securityContextString);
|
||||||
final String securityContextTrimmed = securityContextString.trim();
|
final String securityContextTrimmed = securityContextString.trim();
|
||||||
try {
|
try {
|
||||||
// java serialization starts with {@link ObjectStreamConstants#STREAM_MAGIC} (0xAC, 0xED) bytes
|
|
||||||
// while trimmed json object starts with '{'
|
|
||||||
if (FALLBACK_TO_JAVA_SERIALIZATION &&
|
|
||||||
(securityContextTrimmed.isEmpty() || securityContextTrimmed.charAt(0) != '{')) {
|
|
||||||
return JAVA_SERIALIZATION.deserialize(securityContextString);
|
|
||||||
}
|
|
||||||
|
|
||||||
return OBJECT_MAPPER.readerFor(SecCtxInfo.class).<SecCtxInfo> readValue(securityContextTrimmed).toSecurityContext();
|
return OBJECT_MAPPER.readerFor(SecCtxInfo.class).<SecCtxInfo> readValue(securityContextTrimmed).toSecurityContext();
|
||||||
} catch (final JsonProcessingException e) {
|
} catch (final JsonProcessingException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
package org.eclipse.hawkbit.security;
|
package org.eclipse.hawkbit.security;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.eclipse.hawkbit.security.SecurityContextSerializer.JAVA_SERIALIZATION;
|
|
||||||
import static org.eclipse.hawkbit.security.SecurityContextSerializer.JSON_SERIALIZATION;
|
import static org.eclipse.hawkbit.security.SecurityContextSerializer.JSON_SERIALIZATION;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -63,24 +62,6 @@ class SecurityContextSerializerTest {
|
|||||||
assertThat(serialized).hasSizeLessThan(4096); // ensure that it is not too big
|
assertThat(serialized).hasSizeLessThan(4096); // ensure that it is not too big
|
||||||
}
|
}
|
||||||
|
|
||||||
// test JSON serialization fallback to java serialization
|
|
||||||
@Test
|
|
||||||
void backwardCompatibilityOfJavaSerialization() {
|
|
||||||
final SecurityContext securityContext = SecurityContextHolder.getContext();
|
|
||||||
securityContext.setAuthentication(
|
|
||||||
new UsernamePasswordAuthenticationToken("user", null, AUTHORITIES.stream().map(SimpleGrantedAuthority::new).toList()));
|
|
||||||
|
|
||||||
final String newSerialized = JSON_SERIALIZATION.serialize(securityContext);
|
|
||||||
final String oldSerialized = JAVA_SERIALIZATION.serialize(securityContext);
|
|
||||||
|
|
||||||
assertThat(oldSerialized).isNotEqualTo(newSerialized);
|
|
||||||
final Authentication deserializedOld = JSON_SERIALIZATION.deserialize(oldSerialized).getAuthentication();
|
|
||||||
final Authentication deserializedNew = JSON_SERIALIZATION.deserialize(newSerialized).getAuthentication();
|
|
||||||
assertThat(SpringSecurityAuditorAware.resolveAuditor(deserializedOld)).hasToString(SpringSecurityAuditorAware.resolveAuditor(deserializedNew));
|
|
||||||
assertThat(deserializedOld.getAuthorities()).isEqualTo(deserializedNew.getAuthorities());
|
|
||||||
assertThat(deserializedOld.isAuthenticated()).isEqualTo(deserializedNew.isAuthenticated());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testUsername() {
|
void testUsername() {
|
||||||
final SecurityContext securityContext = SecurityContextHolder.getContext();
|
final SecurityContext securityContext = SecurityContextHolder.getContext();
|
||||||
|
|||||||
Reference in New Issue
Block a user