Remove download by downloadId functionality (#1820)
This functionallity seems to get via AMQP (after some authentication) a private (wihtout need of authentication) url to an artifact assigned to the controller. By default, DDI or DMF shall provide proper urls (for direct download) to devices and if they have to be without authentication this shall be solved in different ways - for instance separate download server providing dedicated private / signed urls. This functinallity is not a real hawkBit part but more like something intended to solve some edge cases. Since it is complicated, heeds support, doesn't solve wide spread use cases, and could be achieved with other means - better to be removed. Signed-off-by: Marinov Avgustin <Avgustin.Marinov@bosch.com>
This commit is contained in:
@@ -1,402 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others
|
||||
*
|
||||
* 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.amqp;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.lenient;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.hawkbit.api.HostnameResolver;
|
||||
import org.eclipse.hawkbit.cache.DownloadIdCache;
|
||||
import org.eclipse.hawkbit.dmf.amqp.api.MessageHeaderKey;
|
||||
import org.eclipse.hawkbit.dmf.amqp.api.MessageType;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DmfDownloadResponse;
|
||||
import org.eclipse.hawkbit.repository.ArtifactManagement;
|
||||
import org.eclipse.hawkbit.repository.ConfirmationManagement;
|
||||
import org.eclipse.hawkbit.repository.ControllerManagement;
|
||||
import org.eclipse.hawkbit.repository.SystemManagement;
|
||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||
import org.eclipse.hawkbit.repository.jpa.JpaEntityFactory;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaArtifact;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleType;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
|
||||
import org.eclipse.hawkbit.repository.model.TenantMetaData;
|
||||
import org.eclipse.hawkbit.security.DdiSecurityProperties;
|
||||
import org.eclipse.hawkbit.security.DdiSecurityProperties.Authentication.Anonymous;
|
||||
import org.eclipse.hawkbit.security.DdiSecurityProperties.Rp;
|
||||
import org.eclipse.hawkbit.security.DmfTenantSecurityToken;
|
||||
import org.eclipse.hawkbit.security.DmfTenantSecurityToken.FileResource;
|
||||
import org.eclipse.hawkbit.security.SecurityContextSerializer;
|
||||
import org.eclipse.hawkbit.security.SecurityContextTenantAware;
|
||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||
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.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.amqp.core.Message;
|
||||
import org.springframework.amqp.core.MessageProperties;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
|
||||
import org.springframework.amqp.support.converter.MessageConverter;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
|
||||
|
||||
import io.qameta.allure.Description;
|
||||
import io.qameta.allure.Feature;
|
||||
import io.qameta.allure.Story;
|
||||
|
||||
/**
|
||||
*
|
||||
* Test Amqp controller authentication.
|
||||
*/
|
||||
@Feature("Component Tests - Device Management Federation API")
|
||||
@Story("AmqpController Authentication Test")
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class AmqpControllerAuthenticationTest {
|
||||
|
||||
private static final String SHA1 = "12345";
|
||||
private static final Long ARTIFACT_ID = 1123L;
|
||||
private static final String TENANT = "DEFAULT";
|
||||
private static final Long TENANT_ID = 123L;
|
||||
private static final String CONTROLLER_ID = "123";
|
||||
private static final Long TARGET_ID = 123L;
|
||||
private AmqpMessageHandlerService amqpMessageHandlerService;
|
||||
private AmqpAuthenticationMessageHandler amqpAuthenticationMessageHandlerService;
|
||||
|
||||
private final MessageConverter messageConverter = new Jackson2JsonMessageConverter();
|
||||
|
||||
private AmqpControllerAuthentication authenticationManager;
|
||||
|
||||
private JpaArtifact testArtifact;
|
||||
|
||||
@Mock
|
||||
private TenantConfigurationManagement tenantConfigurationManagementMock;
|
||||
|
||||
@Mock
|
||||
private SystemManagement systemManagement;
|
||||
|
||||
@Mock
|
||||
private DownloadIdCache cacheMock;
|
||||
|
||||
@Mock
|
||||
private HostnameResolver hostnameResolverMock;
|
||||
|
||||
@Mock
|
||||
private ArtifactManagement artifactManagementMock;
|
||||
|
||||
@Mock
|
||||
private Target targetMock;
|
||||
|
||||
@Mock
|
||||
private UserAuthoritiesResolver authoritiesResolver;
|
||||
|
||||
@Mock
|
||||
private SecurityContextSerializer securityContextSerializer;
|
||||
|
||||
@Mock
|
||||
private RabbitTemplate rabbitTemplate;
|
||||
|
||||
@Mock
|
||||
private ControllerManagement controllerManagement;
|
||||
|
||||
@Mock
|
||||
private ConfirmationManagement confirmationManagement;
|
||||
|
||||
@Mock
|
||||
private DdiSecurityProperties securityProperties;
|
||||
|
||||
@Mock
|
||||
private Rp rp;
|
||||
|
||||
@Mock
|
||||
private DdiSecurityProperties.Authentication ddiAuthentication;
|
||||
|
||||
@Mock
|
||||
private Anonymous anonymous;
|
||||
|
||||
private static final TenantConfigurationValue<Boolean> CONFIG_VALUE_FALSE = TenantConfigurationValue
|
||||
.<Boolean> builder().value(Boolean.FALSE).build();
|
||||
|
||||
private static final TenantConfigurationValue<Boolean> CONFIG_VALUE_TRUE = TenantConfigurationValue
|
||||
.<Boolean> builder().value(Boolean.TRUE).build();
|
||||
|
||||
@BeforeEach
|
||||
public void before() {
|
||||
when(securityProperties.getRp()).thenReturn(rp);
|
||||
when(rp.getSslIssuerHashHeader()).thenReturn("X-Ssl-Issuer-Hash-%d");
|
||||
when(tenantConfigurationManagementMock.getConfigurationValue(any(), eq(Boolean.class)))
|
||||
.thenReturn(CONFIG_VALUE_FALSE);
|
||||
|
||||
final SecurityContextTenantAware tenantAware = new SecurityContextTenantAware(authoritiesResolver, securityContextSerializer);
|
||||
final SystemSecurityContext systemSecurityContext = new SystemSecurityContext(tenantAware);
|
||||
|
||||
authenticationManager = new AmqpControllerAuthentication(systemManagement, controllerManagement,
|
||||
tenantConfigurationManagementMock, tenantAware, securityProperties, systemSecurityContext);
|
||||
|
||||
authenticationManager.postConstruct();
|
||||
|
||||
testArtifact = new JpaArtifact(SHA1, "afilename",
|
||||
new JpaSoftwareModule(new JpaSoftwareModuleType("a key", "a name", null, 1), "a name", "a version"));
|
||||
testArtifact.setId(1L);
|
||||
|
||||
amqpMessageHandlerService = new AmqpMessageHandlerService(rabbitTemplate,
|
||||
mock(AmqpMessageDispatcherService.class), controllerManagement, new JpaEntityFactory(),
|
||||
systemSecurityContext, tenantConfigurationManagementMock, confirmationManagement);
|
||||
|
||||
amqpAuthenticationMessageHandlerService = new AmqpAuthenticationMessageHandler(rabbitTemplate,
|
||||
authenticationManager, artifactManagementMock, cacheMock, hostnameResolverMock, controllerManagement,
|
||||
tenantAware);
|
||||
}
|
||||
|
||||
private void mockAuthenticationWithoutPrincipal() {
|
||||
lenient().when(securityProperties.getAuthentication()).thenReturn(ddiAuthentication);
|
||||
lenient().when(ddiAuthentication.getAnonymous()).thenReturn(anonymous);
|
||||
lenient().when(anonymous.isEnabled()).thenReturn(false);
|
||||
}
|
||||
|
||||
private void mockSuccessfulAuthentication() throws MalformedURLException {
|
||||
when(rabbitTemplate.getMessageConverter()).thenReturn(messageConverter);
|
||||
when(hostnameResolverMock.resolveHostname()).thenReturn(new URL("http://localhost"));
|
||||
when(tenantConfigurationManagementMock.getConfigurationValue(
|
||||
eq(TenantConfigurationKey.AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED), eq(Boolean.class)))
|
||||
.thenReturn(CONFIG_VALUE_TRUE);
|
||||
when(targetMock.getSecurityToken()).thenReturn(CONTROLLER_ID);
|
||||
when(targetMock.getControllerId()).thenReturn(CONTROLLER_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests authentication manager without principal")
|
||||
public void testAuthenticationBadCredentialsWithoutPrincipal() {
|
||||
final DmfTenantSecurityToken securityToken = new DmfTenantSecurityToken(TENANT, TENANT_ID, CONTROLLER_ID,
|
||||
TARGET_ID, FileResource.createFileResourceBySha1(SHA1));
|
||||
|
||||
mockAuthenticationWithoutPrincipal();
|
||||
|
||||
assertThatExceptionOfType(BadCredentialsException.class)
|
||||
.as("BadCredentialsException was expected since principal was missing")
|
||||
.isThrownBy(() -> authenticationManager.doAuthenticate(securityToken));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests authentication manager without wrong credential")
|
||||
public void testAuthenticationBadCredentialsWithWrongCredential() {
|
||||
final DmfTenantSecurityToken securityToken = new DmfTenantSecurityToken(TENANT, TENANT_ID, CONTROLLER_ID,
|
||||
TARGET_ID, FileResource.createFileResourceBySha1(SHA1));
|
||||
|
||||
when(tenantConfigurationManagementMock.getConfigurationValue(
|
||||
eq(TenantConfigurationKey.AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED), eq(Boolean.class)))
|
||||
.thenReturn(CONFIG_VALUE_TRUE);
|
||||
|
||||
securityToken.putHeader(DmfTenantSecurityToken.AUTHORIZATION_HEADER, "TargetToken 12" + CONTROLLER_ID);
|
||||
|
||||
assertThatExceptionOfType(BadCredentialsException.class)
|
||||
.as("BadCredentialsException was expected due to wrong credential")
|
||||
.isThrownBy(() -> authenticationManager.doAuthenticate(securityToken));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests authentication successful")
|
||||
public void testSuccessfulAuthentication() {
|
||||
|
||||
when(controllerManagement.get(any(Long.class))).thenReturn(Optional.of(targetMock));
|
||||
|
||||
final DmfTenantSecurityToken securityToken = new DmfTenantSecurityToken(TENANT, TENANT_ID, CONTROLLER_ID,
|
||||
TARGET_ID, FileResource.createFileResourceBySha1(SHA1));
|
||||
|
||||
when(tenantConfigurationManagementMock.getConfigurationValue(
|
||||
eq(TenantConfigurationKey.AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED), eq(Boolean.class)))
|
||||
.thenReturn(CONFIG_VALUE_TRUE);
|
||||
when(targetMock.getSecurityToken()).thenReturn(CONTROLLER_ID);
|
||||
when(targetMock.getControllerId()).thenReturn(CONTROLLER_ID);
|
||||
|
||||
securityToken.putHeader(DmfTenantSecurityToken.AUTHORIZATION_HEADER, "TargetToken " + CONTROLLER_ID);
|
||||
final Authentication authentication = authenticationManager.doAuthenticate(securityToken);
|
||||
assertThat(authentication).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests authentication message without principal")
|
||||
public void testAuthenticationMessageBadCredentialsWithoutPrincipal() {
|
||||
final MessageProperties messageProperties = createMessageProperties(null);
|
||||
final DmfTenantSecurityToken securityToken = new DmfTenantSecurityToken(TENANT, TENANT_ID, CONTROLLER_ID,
|
||||
TARGET_ID, FileResource.createFileResourceBySha1(SHA1));
|
||||
|
||||
mockAuthenticationWithoutPrincipal();
|
||||
when(rabbitTemplate.getMessageConverter()).thenReturn(messageConverter);
|
||||
|
||||
final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
|
||||
messageProperties);
|
||||
|
||||
// test
|
||||
final Message onMessage = amqpAuthenticationMessageHandlerService.onAuthenticationRequest(message);
|
||||
|
||||
// verify
|
||||
final DmfDownloadResponse downloadResponse = (DmfDownloadResponse) messageConverter.fromMessage(onMessage);
|
||||
assertThat(downloadResponse).isNotNull();
|
||||
assertThat(downloadResponse.getResponseCode()).isEqualTo(HttpStatus.FORBIDDEN.value());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests authentication message without wrong credential")
|
||||
public void testAuthenticationMessageBadCredentialsWithWrongCredential() {
|
||||
final MessageProperties messageProperties = createMessageProperties(null);
|
||||
final DmfTenantSecurityToken securityToken = new DmfTenantSecurityToken(TENANT, TENANT_ID, CONTROLLER_ID,
|
||||
TARGET_ID, FileResource.createFileResourceBySha1(SHA1));
|
||||
|
||||
when(tenantConfigurationManagementMock.getConfigurationValue(
|
||||
eq(TenantConfigurationKey.AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED), eq(Boolean.class)))
|
||||
.thenReturn(CONFIG_VALUE_TRUE);
|
||||
|
||||
when(rabbitTemplate.getMessageConverter()).thenReturn(messageConverter);
|
||||
|
||||
securityToken.putHeader(DmfTenantSecurityToken.AUTHORIZATION_HEADER, "TargetToken 12" + CONTROLLER_ID);
|
||||
final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
|
||||
messageProperties);
|
||||
|
||||
// test
|
||||
final Message onMessage = amqpAuthenticationMessageHandlerService.onAuthenticationRequest(message);
|
||||
|
||||
// verify
|
||||
final DmfDownloadResponse downloadResponse = (DmfDownloadResponse) messageConverter.fromMessage(onMessage);
|
||||
assertThat(downloadResponse).isNotNull();
|
||||
assertThat(downloadResponse.getResponseCode()).isEqualTo(HttpStatus.FORBIDDEN.value());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests authentication message successful")
|
||||
public void successfulMessageAuthentication() throws Exception {
|
||||
|
||||
final MessageProperties messageProperties = createMessageProperties(null);
|
||||
final DmfTenantSecurityToken securityToken = new DmfTenantSecurityToken(TENANT, null, CONTROLLER_ID, null,
|
||||
FileResource.createFileResourceBySha1(SHA1));
|
||||
|
||||
mockSuccessfulAuthentication();
|
||||
when(controllerManagement.getByControllerId(anyString())).thenReturn(Optional.of(targetMock));
|
||||
when(controllerManagement.hasTargetArtifactAssigned(CONTROLLER_ID, SHA1)).thenReturn(true);
|
||||
when(artifactManagementMock.findFirstBySHA1(SHA1)).thenReturn(Optional.of(testArtifact));
|
||||
|
||||
securityToken.putHeader(DmfTenantSecurityToken.AUTHORIZATION_HEADER, "TargetToken " + CONTROLLER_ID);
|
||||
final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
|
||||
messageProperties);
|
||||
|
||||
// test
|
||||
final Message onMessage = amqpAuthenticationMessageHandlerService.onAuthenticationRequest(message);
|
||||
|
||||
// verify
|
||||
final DmfDownloadResponse downloadResponse = (DmfDownloadResponse) messageConverter.fromMessage(onMessage);
|
||||
assertThat(downloadResponse).isNotNull();
|
||||
assertThat(downloadResponse.getDownloadUrl()).isNotNull();
|
||||
assertThat(downloadResponse.getResponseCode()).isEqualTo(HttpStatus.OK.value());
|
||||
assertThat(SecurityContextHolder.getContext()).isNotNull();
|
||||
assertThat(SecurityContextHolder.getContext().getAuthentication()).isNotNull();
|
||||
assertThat(SecurityContextHolder.getContext().getAuthentication().getClass().getName())
|
||||
.isEqualTo(PreAuthenticatedAuthenticationToken.class.getName());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests authentication message successful with targetId intead of controllerId provided and artifactId instead of SHA1.")
|
||||
public void successfulMessageAuthenticationWithTargetIdAndArtifactId() throws Exception {
|
||||
final MessageProperties messageProperties = createMessageProperties(null);
|
||||
final DmfTenantSecurityToken securityToken = new DmfTenantSecurityToken(TENANT, null, null, TARGET_ID,
|
||||
FileResource.createFileResourceByArtifactId(ARTIFACT_ID));
|
||||
|
||||
mockSuccessfulAuthentication();
|
||||
when(controllerManagement.get(any(Long.class))).thenReturn(Optional.of(targetMock));
|
||||
when(controllerManagement.hasTargetArtifactAssigned(TARGET_ID, SHA1)).thenReturn(true);
|
||||
when(artifactManagementMock.get(ARTIFACT_ID)).thenReturn(Optional.of(testArtifact));
|
||||
|
||||
securityToken.putHeader(DmfTenantSecurityToken.AUTHORIZATION_HEADER, "TargetToken " + CONTROLLER_ID);
|
||||
final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
|
||||
messageProperties);
|
||||
|
||||
// test
|
||||
final Message onMessage = amqpAuthenticationMessageHandlerService.onAuthenticationRequest(message);
|
||||
|
||||
// verify
|
||||
final DmfDownloadResponse downloadResponse = (DmfDownloadResponse) messageConverter.fromMessage(onMessage);
|
||||
assertThat(downloadResponse).isNotNull();
|
||||
assertThat(downloadResponse.getDownloadUrl()).isNotNull();
|
||||
assertThat(downloadResponse.getResponseCode()).isEqualTo(HttpStatus.OK.value());
|
||||
assertThat(SecurityContextHolder.getContext()).isNotNull();
|
||||
assertThat(SecurityContextHolder.getContext().getAuthentication()).isNotNull();
|
||||
assertThat(SecurityContextHolder.getContext().getAuthentication().getClass().getName())
|
||||
.isEqualTo(PreAuthenticatedAuthenticationToken.class.getName());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests authentication message successful")
|
||||
public void successfulMessageAuthenticationWithTenantId() throws Exception {
|
||||
|
||||
final MessageProperties messageProperties = createMessageProperties(null);
|
||||
final DmfTenantSecurityToken securityToken = new DmfTenantSecurityToken(null, TENANT_ID, CONTROLLER_ID,
|
||||
TARGET_ID, FileResource.createFileResourceBySha1(SHA1));
|
||||
final TenantMetaData tenantMetaData = mock(TenantMetaData.class);
|
||||
|
||||
mockSuccessfulAuthentication();
|
||||
when(controllerManagement.get(any(Long.class))).thenReturn(Optional.of(targetMock));
|
||||
when(controllerManagement.hasTargetArtifactAssigned(CONTROLLER_ID, SHA1)).thenReturn(true);
|
||||
when(artifactManagementMock.findFirstBySHA1(SHA1)).thenReturn(Optional.of(testArtifact));
|
||||
when(tenantMetaData.getTenant()).thenReturn(TENANT);
|
||||
when(systemManagement.getTenantMetadata(TENANT_ID)).thenReturn(tenantMetaData);
|
||||
|
||||
securityToken.putHeader(DmfTenantSecurityToken.AUTHORIZATION_HEADER, "TargetToken " + CONTROLLER_ID);
|
||||
final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
|
||||
messageProperties);
|
||||
|
||||
// test
|
||||
final Message onMessage = amqpAuthenticationMessageHandlerService.onAuthenticationRequest(message);
|
||||
|
||||
// verify
|
||||
final DmfDownloadResponse downloadResponse = (DmfDownloadResponse) messageConverter.fromMessage(onMessage);
|
||||
assertThat(downloadResponse).isNotNull();
|
||||
assertThat(downloadResponse.getDownloadUrl()).isNotNull();
|
||||
assertThat(downloadResponse.getResponseCode()).isEqualTo(HttpStatus.OK.value());
|
||||
assertThat(SecurityContextHolder.getContext()).isNotNull();
|
||||
assertThat(SecurityContextHolder.getContext().getAuthentication()).isNotNull();
|
||||
assertThat(SecurityContextHolder.getContext().getAuthentication().getClass().getName())
|
||||
.isEqualTo(PreAuthenticatedAuthenticationToken.class.getName());
|
||||
|
||||
}
|
||||
|
||||
private MessageProperties createMessageProperties(final MessageType type) {
|
||||
return createMessageProperties(type, "MyTest");
|
||||
}
|
||||
|
||||
private MessageProperties createMessageProperties(final MessageType type, final String replyTo) {
|
||||
final MessageProperties messageProperties = new MessageProperties();
|
||||
if (type != null) {
|
||||
messageProperties.setHeader(MessageHeaderKey.TYPE, type.name());
|
||||
}
|
||||
messageProperties.setHeader(MessageHeaderKey.TENANT, TENANT);
|
||||
messageProperties.setContentType(MessageProperties.CONTENT_TYPE_JSON);
|
||||
messageProperties.setReplyTo(replyTo);
|
||||
return messageProperties;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -22,15 +22,10 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.hawkbit.api.HostnameResolver;
|
||||
import org.eclipse.hawkbit.artifact.repository.ArtifactRepository;
|
||||
import org.eclipse.hawkbit.cache.DownloadIdCache;
|
||||
import org.eclipse.hawkbit.dmf.amqp.api.EventTopic;
|
||||
import org.eclipse.hawkbit.dmf.amqp.api.MessageHeaderKey;
|
||||
import org.eclipse.hawkbit.dmf.amqp.api.MessageType;
|
||||
@@ -39,9 +34,7 @@ import org.eclipse.hawkbit.dmf.json.model.DmfActionUpdateStatus;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DmfAttributeUpdate;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DmfAutoConfirmation;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DmfCreateThing;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DmfDownloadResponse;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DmfUpdateMode;
|
||||
import org.eclipse.hawkbit.repository.ArtifactManagement;
|
||||
import org.eclipse.hawkbit.repository.ConfirmationManagement;
|
||||
import org.eclipse.hawkbit.repository.ControllerManagement;
|
||||
import org.eclipse.hawkbit.repository.EntityFactory;
|
||||
@@ -54,19 +47,14 @@ import org.eclipse.hawkbit.repository.jpa.builder.JpaActionStatusBuilder;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.SecurityTokenGeneratorHolder;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
import org.eclipse.hawkbit.repository.model.ActionProperties;
|
||||
import org.eclipse.hawkbit.repository.model.Artifact;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
|
||||
import org.eclipse.hawkbit.security.DmfTenantSecurityToken;
|
||||
import org.eclipse.hawkbit.security.DmfTenantSecurityToken.FileResource;
|
||||
import org.eclipse.hawkbit.security.SecurityContextSerializer;
|
||||
import org.eclipse.hawkbit.security.SecurityContextTenantAware;
|
||||
import org.eclipse.hawkbit.security.SecurityTokenGenerator;
|
||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.eclipse.hawkbit.tenancy.UserAuthoritiesResolver;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -82,7 +70,6 @@ import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
|
||||
import org.springframework.amqp.support.converter.MessageConversionException;
|
||||
import org.springframework.amqp.support.converter.MessageConverter;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
import io.qameta.allure.Description;
|
||||
import io.qameta.allure.Feature;
|
||||
@@ -97,15 +84,10 @@ public class AmqpMessageHandlerServiceTest {
|
||||
private static final String FAIL_MESSAGE_AMQP_REJECT_REASON = AmqpRejectAndDontRequeueException.class
|
||||
.getSimpleName() + " was expected, ";
|
||||
|
||||
private static final String SHA1 = "12345";
|
||||
private static final String VIRTUAL_HOST = "vHost";
|
||||
private static final String TENANT = "DEFAULT";
|
||||
private static final Long TENANT_ID = 123L;
|
||||
private static final String CONTROLLER_ID = "123";
|
||||
private static final Long TARGET_ID = 123L;
|
||||
|
||||
private AmqpMessageHandlerService amqpMessageHandlerService;
|
||||
private AmqpAuthenticationMessageHandler amqpAuthenticationMessageHandlerService;
|
||||
|
||||
private MessageConverter messageConverter;
|
||||
|
||||
@@ -117,67 +99,37 @@ public class AmqpMessageHandlerServiceTest {
|
||||
|
||||
@Mock
|
||||
private ConfirmationManagement confirmationManagementMock;
|
||||
|
||||
@Mock
|
||||
private EntityFactory entityFactoryMock;
|
||||
|
||||
@Mock
|
||||
private ArtifactManagement artifactManagementMock;
|
||||
|
||||
@Mock
|
||||
private TenantConfigurationManagement tenantConfigurationManagement;
|
||||
|
||||
@Mock
|
||||
private AmqpControllerAuthentication authenticationManagerMock;
|
||||
|
||||
@Mock
|
||||
private ArtifactRepository artifactRepositoryMock;
|
||||
|
||||
@Mock
|
||||
private DownloadIdCache downloadIdCache;
|
||||
|
||||
@Mock
|
||||
private HostnameResolver hostnameResolverMock;
|
||||
|
||||
@Mock
|
||||
private RabbitTemplate rabbitTemplate;
|
||||
|
||||
@Mock
|
||||
private TenantAware tenantAwareMock;
|
||||
|
||||
@Mock
|
||||
private UserAuthoritiesResolver authoritiesResolver;
|
||||
|
||||
@Mock
|
||||
private SecurityContextSerializer securityContextSerializer;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<Map<String, String>> attributesCaptor;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<String> targetIdCaptor;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<String> initiatorCaptor;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<String> remarkCaptor;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<String> targetNameCaptor;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<String> targetTypeNameCaptor;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<URI> uriCaptor;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<UpdateMode> modeCaptor;
|
||||
|
||||
@BeforeEach
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public void before() throws Exception {
|
||||
public void before() {
|
||||
messageConverter = new Jackson2JsonMessageConverter();
|
||||
lenient().when(rabbitTemplate.getMessageConverter()).thenReturn(messageConverter);
|
||||
final TenantConfigurationValue multiAssignmentConfig = TenantConfigurationValue.builder().value(Boolean.FALSE)
|
||||
@@ -191,9 +143,6 @@ public class AmqpMessageHandlerServiceTest {
|
||||
amqpMessageHandlerService = new AmqpMessageHandlerService(rabbitTemplate, amqpMessageDispatcherServiceMock,
|
||||
controllerManagementMock, entityFactoryMock, systemSecurityContext, tenantConfigurationManagement,
|
||||
confirmationManagementMock);
|
||||
amqpAuthenticationMessageHandlerService = new AmqpAuthenticationMessageHandler(rabbitTemplate,
|
||||
authenticationManagerMock, artifactManagementMock, downloadIdCache, hostnameResolverMock,
|
||||
controllerManagementMock, tenantAwareMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -549,85 +498,12 @@ public class AmqpMessageHandlerServiceTest {
|
||||
VIRTUAL_HOST));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests that an download request is denied for an artifact which does not exists")
|
||||
public void authenticationRequestDeniedForArtifactWhichDoesNotExists() {
|
||||
final MessageProperties messageProperties = createMessageProperties(null);
|
||||
final DmfTenantSecurityToken securityToken = new DmfTenantSecurityToken(TENANT, TENANT_ID, CONTROLLER_ID,
|
||||
TARGET_ID, FileResource.createFileResourceBySha1("12345"));
|
||||
final Message message = createMessage(securityToken, messageProperties);
|
||||
|
||||
// test
|
||||
final Message onMessage = amqpAuthenticationMessageHandlerService.onAuthenticationRequest(message);
|
||||
|
||||
// verify
|
||||
final DmfDownloadResponse downloadResponse = (DmfDownloadResponse) messageConverter.fromMessage(onMessage);
|
||||
assertThat(downloadResponse).as("Message body should not null").isNotNull();
|
||||
assertThat(downloadResponse.getResponseCode()).as("Message body response code is wrong")
|
||||
.isEqualTo(HttpStatus.NOT_FOUND.value());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests that an download request is denied for an artifact which is not assigned to the requested target")
|
||||
public void authenticationRequestDeniedForArtifactWhichIsNotAssignedToTarget() {
|
||||
final MessageProperties messageProperties = createMessageProperties(null);
|
||||
final DmfTenantSecurityToken securityToken = new DmfTenantSecurityToken(TENANT, TENANT_ID, CONTROLLER_ID,
|
||||
TARGET_ID, FileResource.createFileResourceBySha1("12345"));
|
||||
final Message message = createMessage(securityToken, messageProperties);
|
||||
|
||||
final Artifact localArtifactMock = mock(Artifact.class);
|
||||
when(artifactManagementMock.findFirstBySHA1(anyString())).thenReturn(Optional.of(localArtifactMock));
|
||||
|
||||
// test
|
||||
final Message onMessage = amqpAuthenticationMessageHandlerService.onAuthenticationRequest(message);
|
||||
|
||||
// verify
|
||||
final DmfDownloadResponse downloadResponse = (DmfDownloadResponse) messageConverter.fromMessage(onMessage);
|
||||
assertThat(downloadResponse).as("Message body should not null").isNotNull();
|
||||
assertThat(downloadResponse.getResponseCode()).as("Message body response code is wrong")
|
||||
.isEqualTo(HttpStatus.NOT_FOUND.value());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests that an download request is allowed for an artifact which exists and assigned to the requested target")
|
||||
public void authenticationRequestAllowedForArtifactWhichExistsAndAssignedToTarget() throws MalformedURLException {
|
||||
final MessageProperties messageProperties = createMessageProperties(null);
|
||||
final DmfTenantSecurityToken securityToken = new DmfTenantSecurityToken(TENANT, TENANT_ID, CONTROLLER_ID,
|
||||
TARGET_ID, FileResource.createFileResourceBySha1("12345"));
|
||||
final Message message = createMessage(securityToken, messageProperties);
|
||||
|
||||
// mock
|
||||
final Artifact localArtifactMock = mock(Artifact.class);
|
||||
when(localArtifactMock.getSha1Hash()).thenReturn(SHA1);
|
||||
when(localArtifactMock.getMd5Hash()).thenReturn("md5");
|
||||
when(localArtifactMock.getSize()).thenReturn(1L);
|
||||
|
||||
when(artifactManagementMock.findFirstBySHA1(SHA1)).thenReturn(Optional.of(localArtifactMock));
|
||||
when(controllerManagementMock.hasTargetArtifactAssigned(securityToken.getControllerId(), SHA1))
|
||||
.thenReturn(true);
|
||||
when(hostnameResolverMock.resolveHostname()).thenReturn(new URL("http://localhost"));
|
||||
|
||||
// test
|
||||
final Message onMessage = amqpAuthenticationMessageHandlerService.onAuthenticationRequest(message);
|
||||
|
||||
// verify
|
||||
final DmfDownloadResponse downloadResponse = (DmfDownloadResponse) messageConverter.fromMessage(onMessage);
|
||||
assertThat(downloadResponse).as("Message body should not null").isNotNull();
|
||||
assertThat(downloadResponse.getResponseCode()).as("Message body response code is wrong")
|
||||
.isEqualTo(HttpStatus.OK.value());
|
||||
assertThat(downloadResponse.getArtifact().getSize()).as("Wrong artifact size in message body").isEqualTo(1L);
|
||||
assertThat(downloadResponse.getArtifact().getHashes().getSha1()).as("Wrong sha1 hash").isEqualTo(SHA1);
|
||||
assertThat(downloadResponse.getArtifact().getHashes().getMd5()).as("Wrong md5 hash").isEqualTo("md5");
|
||||
assertThat(downloadResponse.getDownloadUrl()).as("download url is wrong")
|
||||
.startsWith("http://localhost/api/v1/downloadserver/downloadId/");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test next update is provided on finished action")
|
||||
public void lookupNextUpdateActionAfterFinished() throws IllegalAccessException {
|
||||
|
||||
// Mock
|
||||
final Action action = createActionWithTarget(22L, Status.FINISHED);
|
||||
final Action action = createActionWithTarget(22L);
|
||||
when(controllerManagementMock.findActionWithDetails(anyLong())).thenReturn(Optional.of(action));
|
||||
when(controllerManagementMock.addUpdateActionStatus(any())).thenReturn(action);
|
||||
final ActionStatusBuilder builder = mock(ActionStatusBuilder.class);
|
||||
@@ -650,8 +526,8 @@ public class AmqpMessageHandlerServiceTest {
|
||||
final ArgumentCaptor<ActionProperties> actionPropertiesCaptor = ArgumentCaptor.forClass(ActionProperties.class);
|
||||
final ArgumentCaptor<Target> targetCaptor = ArgumentCaptor.forClass(Target.class);
|
||||
|
||||
verify(amqpMessageDispatcherServiceMock, times(1)).sendUpdateMessageToTarget(actionPropertiesCaptor.capture(),
|
||||
targetCaptor.capture(), any(Map.class));
|
||||
verify(amqpMessageDispatcherServiceMock, times(1))
|
||||
.sendUpdateMessageToTarget(actionPropertiesCaptor.capture(), targetCaptor.capture(), any(Map.class));
|
||||
final ActionProperties actionProperties = actionPropertiesCaptor.getValue();
|
||||
assertThat(actionProperties).isNotNull();
|
||||
assertThat(actionProperties.getTenant()).as("event has tenant").isEqualTo("DEFAULT");
|
||||
@@ -664,7 +540,7 @@ public class AmqpMessageHandlerServiceTest {
|
||||
public void feedBackCodeIsPersistedInMessages() throws IllegalAccessException {
|
||||
|
||||
// Mock
|
||||
final Action action = createActionWithTarget(22L, Status.FINISHED);
|
||||
final Action action = createActionWithTarget(22L);
|
||||
when(controllerManagementMock.findActionWithDetails(anyLong())).thenReturn(Optional.of(action));
|
||||
when(controllerManagementMock.addUpdateActionStatus(any())).thenReturn(action);
|
||||
final ActionStatusBuilder builder = new JpaActionStatusBuilder();
|
||||
@@ -770,7 +646,7 @@ public class AmqpMessageHandlerServiceTest {
|
||||
return messageProperties;
|
||||
}
|
||||
|
||||
private Action createActionWithTarget(final Long targetId, final Status status) throws IllegalAccessException {
|
||||
private Action createActionWithTarget(final Long targetId) throws IllegalAccessException {
|
||||
// is needed for the creation of targets
|
||||
initializeSecurityTokenGenerator();
|
||||
|
||||
|
||||
@@ -1,462 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others
|
||||
*
|
||||
* 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.integration;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.amqp.AmqpProperties;
|
||||
import org.eclipse.hawkbit.amqp.DmfApiConfiguration;
|
||||
import org.eclipse.hawkbit.dmf.amqp.api.AmqpSettings;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DmfDownloadResponse;
|
||||
import org.eclipse.hawkbit.rabbitmq.test.AbstractAmqpIntegrationTest;
|
||||
import org.eclipse.hawkbit.repository.model.Artifact;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.security.DmfTenantSecurityToken;
|
||||
import org.eclipse.hawkbit.security.DmfTenantSecurityToken.FileResource;
|
||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.amqp.core.Message;
|
||||
import org.springframework.amqp.core.MessageProperties;
|
||||
import org.springframework.amqp.rabbit.core.RabbitAdmin;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import io.qameta.allure.Description;
|
||||
import io.qameta.allure.Feature;
|
||||
import io.qameta.allure.Story;
|
||||
|
||||
@Feature("Component Tests - Device Management Federation API")
|
||||
@Story("Amqp Authentication Message Handler")
|
||||
@SpringBootTest(classes = { DmfApiConfiguration.class })
|
||||
public class AmqpAuthenticationMessageHandlerIntegrationTest extends AbstractAmqpIntegrationTest {
|
||||
|
||||
private static final String TARGET_SECRUITY_TOKEN = "12345";
|
||||
private static final String TARGET_TOKEN_HEADER = "TargetToken " + TARGET_SECRUITY_TOKEN;
|
||||
private static final String TENANT_EXIST = "DEFAULT";
|
||||
private static final String TARGET = "NewDmfTarget";
|
||||
|
||||
@Autowired
|
||||
private AmqpProperties amqpProperties;
|
||||
|
||||
@BeforeEach
|
||||
public void testSetup() {
|
||||
enableTargetTokenAuthentication();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests wrong content type. This message is invalid and should not be requeued. Additional the receive message is null")
|
||||
public void wrongContentType() {
|
||||
final Message createAndSendMessage = getDmfClient()
|
||||
.sendAndReceive(new Message("".getBytes(), new MessageProperties()));
|
||||
assertThat(createAndSendMessage).isNull();
|
||||
assertEmptyAuthenticationMessageCount();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests a null message. This message is invalid and should not be requeued. Additional the receive message is null")
|
||||
public void securityTokenIsNull() {
|
||||
final Message createAndSendMessage = sendAndReceiveAuthenticationMessage(null);
|
||||
assertThat(createAndSendMessage).isNull();
|
||||
assertEmptyAuthenticationMessageCount();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tenant in the message is null. This message is invalid and should not be requeued. Additional the receive message is null")
|
||||
public void securityTokenTenantIsNull() {
|
||||
final DmfTenantSecurityToken securityToken = createTenantSecurityToken(null, TARGET,
|
||||
FileResource.createFileResourceBySha1(TARGET_SECRUITY_TOKEN));
|
||||
final Message createAndSendMessage = sendAndReceiveAuthenticationMessage(securityToken);
|
||||
assertThat(createAndSendMessage).isNull();
|
||||
assertEmptyAuthenticationMessageCount();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Target in the message is null.This message is invalid and should not requeued. Additional the receive message is null")
|
||||
public void securityTokenFileResourceIsNull() {
|
||||
enableAnonymousAuthentication();
|
||||
final DmfTenantSecurityToken securityToken = createTenantSecurityToken(TENANT_EXIST, TARGET, null);
|
||||
final Message returnMessage = sendAndReceiveAuthenticationMessage(securityToken);
|
||||
verifyResult(returnMessage, HttpStatus.NOT_FOUND, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that login fails if the given credential not match.")
|
||||
public void loginFailedBadCredentials() {
|
||||
tenantConfigurationManagement.addOrUpdateConfiguration(TenantConfigurationKey.ANONYMOUS_DOWNLOAD_MODE_ENABLED,
|
||||
false);
|
||||
final DmfTenantSecurityToken securityToken = createTenantSecurityToken(TENANT_EXIST, TARGET,
|
||||
FileResource.createFileResourceBySha1(TARGET_SECRUITY_TOKEN));
|
||||
final Message createAndSendMessage = sendAndReceiveAuthenticationMessage(securityToken);
|
||||
|
||||
verifyResult(createAndSendMessage, HttpStatus.FORBIDDEN, "Login failed");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that the receive message contains a 404 code,if the artifact could not found")
|
||||
public void fileResourceGetSha1InSecurityTokenIsNull() {
|
||||
enableAnonymousAuthentication();
|
||||
final DmfTenantSecurityToken securityToken = createTenantSecurityToken(TENANT_EXIST, TARGET,
|
||||
FileResource.createFileResourceBySha1(null));
|
||||
|
||||
final Message returnMessage = sendAndReceiveAuthenticationMessage(securityToken);
|
||||
verifyResult(returnMessage, HttpStatus.NOT_FOUND,
|
||||
"Artifact for resource FileResource [sha1=null, artifactId=null, filename=null] not found ");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that the receive message contains a 404 code , if the distributionSet is not assigned to the target")
|
||||
public void artifactForFileResourceSHA1FoundByTargetIdTargetExistsButIsNotAssigned() {
|
||||
final Target target = createTarget(TARGET);
|
||||
|
||||
final DistributionSet distributionSet = createDistributionSet();
|
||||
final List<Artifact> artifacts = createArtifacts(distributionSet);
|
||||
final String sha1Hash = artifacts.get(0).getSha1Hash();
|
||||
final DmfTenantSecurityToken securityToken = createTenantSecurityToken(target.getTenant(), target.getId(), null,
|
||||
FileResource.createFileResourceBySha1(sha1Hash));
|
||||
|
||||
final Message returnMessage = sendAndReceiveAuthenticationMessage(securityToken);
|
||||
verifyResult(returnMessage, HttpStatus.NOT_FOUND, "Artifact for resource FileResource [sha1=" + sha1Hash
|
||||
+ ", artifactId=null, filename=null] not found ");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that the receive message contains a 404 code, if there is no artifact for the given sha1")
|
||||
public void artifactForFileResourceSHA1NotFound() {
|
||||
enableAnonymousAuthentication();
|
||||
final DmfTenantSecurityToken securityToken = createTenantSecurityToken(TENANT_EXIST, TARGET,
|
||||
FileResource.createFileResourceBySha1(TARGET_SECRUITY_TOKEN));
|
||||
|
||||
final Message returnMessage = sendAndReceiveAuthenticationMessage(securityToken);
|
||||
verifyResult(returnMessage, HttpStatus.NOT_FOUND,
|
||||
"Artifact for resource FileResource [sha1=12345, artifactId=null, filename=null] not found ");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that the receive message contains a 404 code, if there is no existing target for the given controller id")
|
||||
public void artifactForFileResourceSHA1FoundTargetNotExists() {
|
||||
enableAnonymousAuthentication();
|
||||
final DistributionSet distributionSet = createDistributionSet();
|
||||
final List<Artifact> artifacts = createArtifacts(distributionSet);
|
||||
final String sha1Hash = artifacts.get(0).getSha1Hash();
|
||||
final DmfTenantSecurityToken securityToken = createTenantSecurityToken(TENANT_EXIST, TARGET,
|
||||
FileResource.createFileResourceBySha1(sha1Hash));
|
||||
|
||||
final Message returnMessage = sendAndReceiveAuthenticationMessage(securityToken);
|
||||
verifyResult(returnMessage, HttpStatus.NOT_FOUND, "Artifact for resource FileResource [sha1=" + sha1Hash
|
||||
+ ", artifactId=null, filename=null] not found ");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that the receive message contains a 404 code, if there is no existing artifact for the target")
|
||||
public void artifactForFileResourceSHA1FoundTargetExistsButNotAssigned() {
|
||||
createTarget(TARGET);
|
||||
|
||||
final DistributionSet distributionSet = createDistributionSet();
|
||||
final List<Artifact> artifacts = createArtifacts(distributionSet);
|
||||
final DmfTenantSecurityToken securityToken = createTenantSecurityToken(TENANT_EXIST, TARGET,
|
||||
FileResource.createFileResourceBySha1(artifacts.get(0).getSha1Hash()));
|
||||
|
||||
final Message returnMessage = sendAndReceiveAuthenticationMessage(securityToken);
|
||||
verifyResult(returnMessage, HttpStatus.NOT_FOUND,
|
||||
"Artifact for resource FileResource [sha1=2f532b93ed23b4341a81dc9b1ee8a1c44b5526ab, artifactId=null, filename=null] not found ");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that the receive message contains a 200 code and a artifact for the existing controller id ")
|
||||
public void artifactForFileResourceSHA1FoundTargetExistsIsAssigned() {
|
||||
createTarget(TARGET);
|
||||
|
||||
final DistributionSet distributionSet = createDistributionSet();
|
||||
final List<Artifact> artifacts = createArtifacts(distributionSet);
|
||||
final Artifact artifact = artifacts.get(0);
|
||||
final DmfTenantSecurityToken securityToken = createTenantSecurityToken(TENANT_EXIST, TARGET,
|
||||
FileResource.createFileResourceBySha1(artifact.getSha1Hash()));
|
||||
|
||||
assignDistributionSet(distributionSet.getId(), TARGET);
|
||||
|
||||
final Message returnMessage = sendAndReceiveAuthenticationMessage(securityToken);
|
||||
verifyOkResult(returnMessage, artifact);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that the receive message contains a 200 code and a artifact for the existing target id ")
|
||||
public void artifactForFileResourceSHA1FoundByTargetIdTargetExistsIsAssigned() {
|
||||
final Target target = createTarget(TARGET);
|
||||
|
||||
final DistributionSet distributionSet = createDistributionSet();
|
||||
final List<Artifact> artifacts = createArtifacts(distributionSet);
|
||||
final Artifact artifact = artifacts.get(0);
|
||||
final DmfTenantSecurityToken securityToken = createTenantSecurityToken(TENANT_EXIST, target.getId(), null,
|
||||
FileResource.createFileResourceBySha1(artifact.getSha1Hash()));
|
||||
|
||||
assignDistributionSet(distributionSet.getId(), TARGET);
|
||||
|
||||
final Message returnMessage = sendAndReceiveAuthenticationMessage(securityToken);
|
||||
verifyOkResult(returnMessage, artifact);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that the receive message contains a 200 code and a artifact without a controller id (anonymous enabled)")
|
||||
public void anonymousAuthentification() {
|
||||
enableAnonymousAuthentication();
|
||||
final DistributionSet distributionSet = createDistributionSet();
|
||||
final List<Artifact> artifacts = createArtifacts(distributionSet);
|
||||
final Artifact artifact = artifacts.get(0);
|
||||
final DmfTenantSecurityToken securityToken = createTenantSecurityToken(TENANT_EXIST, null, null,
|
||||
FileResource.createFileResourceBySha1(artifact.getSha1Hash()));
|
||||
|
||||
final Message returnMessage = sendAndReceiveAuthenticationMessage(securityToken);
|
||||
verifyOkResult(returnMessage, artifact);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Artifact is downloaded anonymous as there is not target id or controller id assigned to the target.")
|
||||
public void targetTokenAuthentification() {
|
||||
createTarget(TARGET);
|
||||
|
||||
final DistributionSet distributionSet = createDistributionSet();
|
||||
final List<Artifact> artifacts = createArtifacts(distributionSet);
|
||||
final Artifact artifact = artifacts.get(0);
|
||||
final DmfTenantSecurityToken securityToken = createTenantSecurityToken(TENANT_EXIST, TARGET,
|
||||
FileResource.createFileResourceBySha1(artifact.getSha1Hash()));
|
||||
|
||||
assignDistributionSet(distributionSet.getId(), TARGET);
|
||||
|
||||
final Message returnMessage = sendAndReceiveAuthenticationMessage(securityToken);
|
||||
verifyOkResult(returnMessage, artifact);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that the receive message contains a 404, if there is no artifact to the given filename")
|
||||
public void artifactForFileResourceFileNameNotFound() {
|
||||
enableAnonymousAuthentication();
|
||||
final DmfTenantSecurityToken securityToken = createTenantSecurityToken(TENANT_EXIST, TARGET,
|
||||
FileResource.createFileResourceByFilename("Test.txt"));
|
||||
|
||||
final Message returnMessage = sendAndReceiveAuthenticationMessage(securityToken);
|
||||
verifyResult(returnMessage, HttpStatus.NOT_FOUND,
|
||||
"Artifact for resource FileResource [sha1=null, artifactId=null, filename=Test.txt] not found ");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that the receive message contains a 404, if there is no distribution set assigned to the target")
|
||||
public void artifactForFileResourceFileNameFoundTargetExistsButNotAssigned() {
|
||||
createTarget(TARGET);
|
||||
|
||||
final DistributionSet distributionSet = createDistributionSet();
|
||||
final List<Artifact> artifacts = createArtifacts(distributionSet);
|
||||
final DmfTenantSecurityToken securityToken = createTenantSecurityToken(TENANT_EXIST, TARGET,
|
||||
FileResource.createFileResourceByFilename(artifacts.get(0).getFilename()));
|
||||
|
||||
final Message returnMessage = sendAndReceiveAuthenticationMessage(securityToken);
|
||||
verifyResult(returnMessage, HttpStatus.NOT_FOUND,
|
||||
"Artifact for resource FileResource [sha1=null, artifactId=null, filename=filename0] not found ");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that the receive message contains a 404, if there is no exisiting target")
|
||||
public void artifactForFileResourceArtifactIdFoundTargetNotExists() {
|
||||
enableAnonymousAuthentication();
|
||||
final DistributionSet distributionSet = createDistributionSet();
|
||||
final List<Artifact> artifacts = createArtifacts(distributionSet);
|
||||
final FileResource fileResource = FileResource.createFileResourceByArtifactId(artifacts.get(0).getId());
|
||||
final DmfTenantSecurityToken securityToken = createTenantSecurityToken(TENANT_EXIST, TARGET, fileResource);
|
||||
|
||||
final Message returnMessage = sendAndReceiveAuthenticationMessage(securityToken);
|
||||
verifyResult(returnMessage, HttpStatus.NOT_FOUND, "Artifact for resource FileResource [sha1=null, artifactId="
|
||||
+ artifacts.get(0).getId() + ", filename=null] not found ");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that the receive message contains a 200 and a artifact for the given artifact id")
|
||||
public void artifactForFileResourceArtifactIdFoundTargetExistsIsAssigned() {
|
||||
createTarget(TARGET);
|
||||
|
||||
final DistributionSet distributionSet = createDistributionSet();
|
||||
final List<Artifact> artifacts = createArtifacts(distributionSet);
|
||||
final Artifact artifact = artifacts.get(0);
|
||||
final FileResource fileResource = FileResource.createFileResourceByArtifactId(artifact.getId());
|
||||
final DmfTenantSecurityToken securityToken = createTenantSecurityToken(TENANT_EXIST, TARGET, fileResource);
|
||||
|
||||
assignDistributionSet(distributionSet.getId(), TARGET);
|
||||
|
||||
final Message returnMessage = sendAndReceiveAuthenticationMessage(securityToken);
|
||||
verifyOkResult(returnMessage, artifact);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that the receive message contains a 404, if there is no artifact to the given softwareModuleFilename")
|
||||
public void artifactForFileResourceSoftwareModuleFilenameNotFound() {
|
||||
enableAnonymousAuthentication();
|
||||
final DmfTenantSecurityToken securityToken = createTenantSecurityToken(TENANT_EXIST, TARGET,
|
||||
FileResource.softwareModuleFilename(1L, "Test.txt"));
|
||||
|
||||
final Message returnMessage = sendAndReceiveAuthenticationMessage(securityToken);
|
||||
verifyResult(returnMessage, HttpStatus.NOT_FOUND,
|
||||
"Artifact for resource FileResource [sha1=null, artifactId=null, filename=null] not found ");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that the receive message contains a 404, if there is no existing target for the file resource")
|
||||
public void artifactForFileResourceSoftwareModuleFilenameFoundTargetNotExists() {
|
||||
enableAnonymousAuthentication();
|
||||
final DistributionSet distributionSet = createDistributionSet();
|
||||
final List<Artifact> artifacts = createArtifacts(distributionSet);
|
||||
|
||||
final SoftwareModule softwareModule = distributionSet.getModules().stream().findFirst().get();
|
||||
final Artifact artifact = findArtifactOfSoftwareModule(artifacts, softwareModule);
|
||||
|
||||
final FileResource fileResource = FileResource.softwareModuleFilename(softwareModule.getId(),
|
||||
softwareModule.getArtifact(artifact.getId()).get().getFilename());
|
||||
final DmfTenantSecurityToken securityToken = createTenantSecurityToken(TENANT_EXIST, TARGET, fileResource);
|
||||
|
||||
final Message returnMessage = sendAndReceiveAuthenticationMessage(securityToken);
|
||||
verifyResult(returnMessage, HttpStatus.NOT_FOUND,
|
||||
"Artifact for resource FileResource [sha1=null, artifactId=null, filename=null] not found ");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that the receive message contains a 200 and a artifact, if there is a existing artifct fpt the for the given softwareModuleFilename")
|
||||
public void artifactForFileResourceSoftwareModuleFilenameFoundTargetExistsIsAssigned() {
|
||||
createTarget(TARGET);
|
||||
|
||||
final DistributionSet distributionSet = createDistributionSet();
|
||||
final List<Artifact> artifacts = createArtifacts(distributionSet);
|
||||
|
||||
final SoftwareModule softwareModule = distributionSet.getModules().stream().findFirst().get();
|
||||
final Artifact artifact = findArtifactOfSoftwareModule(artifacts, softwareModule);
|
||||
|
||||
final FileResource fileResource = FileResource.softwareModuleFilename(softwareModule.getId(),
|
||||
softwareModule.getArtifact(artifact.getId()).get().getFilename());
|
||||
final DmfTenantSecurityToken securityToken = createTenantSecurityToken(TENANT_EXIST, TARGET, fileResource);
|
||||
|
||||
assignDistributionSet(distributionSet.getId(), TARGET);
|
||||
|
||||
final Message returnMessage = sendAndReceiveAuthenticationMessage(securityToken);
|
||||
verifyOkResult(returnMessage, artifact);
|
||||
|
||||
}
|
||||
|
||||
private void verifyOkResult(final Message returnMessage, final Artifact artifact) {
|
||||
final DmfDownloadResponse convertedMessage = verifyResult(returnMessage, HttpStatus.OK, null);
|
||||
assertThat(convertedMessage.getDownloadUrl()).isNotNull();
|
||||
assertThat(convertedMessage.getArtifact()).isNotNull();
|
||||
assertThat(convertedMessage.getArtifact().getLastModified())
|
||||
.isEqualTo(artifactManagement.findFirstBySHA1(artifact.getSha1Hash()).get().getCreatedAt());
|
||||
assertThat(convertedMessage.getArtifact().getHashes().getSha1()).isEqualTo(artifact.getSha1Hash());
|
||||
|
||||
}
|
||||
|
||||
private void enableAnonymousAuthentication() {
|
||||
tenantConfigurationManagement.addOrUpdateConfiguration(TenantConfigurationKey.ANONYMOUS_DOWNLOAD_MODE_ENABLED,
|
||||
true);
|
||||
tenantConfigurationManagement.addOrUpdateConfiguration(
|
||||
TenantConfigurationKey.AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED, false);
|
||||
}
|
||||
|
||||
private void enableTargetTokenAuthentication() {
|
||||
tenantConfigurationManagement.addOrUpdateConfiguration(TenantConfigurationKey.ANONYMOUS_DOWNLOAD_MODE_ENABLED,
|
||||
false);
|
||||
tenantConfigurationManagement.addOrUpdateConfiguration(
|
||||
TenantConfigurationKey.AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED, true);
|
||||
}
|
||||
|
||||
private Target createTarget(final String controllerId) {
|
||||
return targetManagement.create(
|
||||
entityFactory.target().create().controllerId(controllerId).securityToken(TARGET_SECRUITY_TOKEN));
|
||||
}
|
||||
|
||||
private DmfTenantSecurityToken createTenantSecurityToken(final String tenant, final String controllerId,
|
||||
final FileResource fileResource) {
|
||||
final DmfTenantSecurityToken tenantSecurityToken = new DmfTenantSecurityToken(tenant, controllerId,
|
||||
fileResource);
|
||||
tenantSecurityToken.putHeader(DmfTenantSecurityToken.AUTHORIZATION_HEADER, TARGET_TOKEN_HEADER);
|
||||
return tenantSecurityToken;
|
||||
}
|
||||
|
||||
private DmfTenantSecurityToken createTenantSecurityToken(final String tenant, final Long targetId,
|
||||
final String controllerId, final FileResource fileResource) {
|
||||
final DmfTenantSecurityToken tenantSecurityToken = new DmfTenantSecurityToken(tenant, null, controllerId,
|
||||
targetId, fileResource);
|
||||
tenantSecurityToken.putHeader(DmfTenantSecurityToken.AUTHORIZATION_HEADER, TARGET_TOKEN_HEADER);
|
||||
return tenantSecurityToken;
|
||||
}
|
||||
|
||||
private DistributionSet createDistributionSet() {
|
||||
return testdataFactory.createDistributionSet("one");
|
||||
}
|
||||
|
||||
private List<Artifact> createArtifacts(final DistributionSet distributionSet) {
|
||||
final List<Artifact> artifacts = new ArrayList<>();
|
||||
for (final SoftwareModule module : distributionSet.getModules()) {
|
||||
artifacts.addAll(testdataFactory.createArtifacts(module.getId()));
|
||||
}
|
||||
return artifacts;
|
||||
}
|
||||
|
||||
private DmfDownloadResponse verifyResult(final Message returnMessage, final HttpStatus expectedStatus,
|
||||
final String expectedMessage) {
|
||||
final DmfDownloadResponse convertedMessage = (DmfDownloadResponse) getDmfClient().getMessageConverter()
|
||||
.fromMessage(returnMessage);
|
||||
assertThat(convertedMessage.getResponseCode()).isEqualTo(expectedStatus.value());
|
||||
|
||||
if (!StringUtils.isEmpty(expectedMessage)) {
|
||||
assertThat(convertedMessage.getMessage()).isEqualTo(expectedMessage);
|
||||
}
|
||||
return convertedMessage;
|
||||
}
|
||||
|
||||
private Message sendAndReceiveAuthenticationMessage(final DmfTenantSecurityToken securityToken) {
|
||||
return getDmfClient().sendAndReceive(createMessage(securityToken, new MessageProperties()));
|
||||
}
|
||||
|
||||
private Artifact findArtifactOfSoftwareModule(final List<Artifact> artifacts, final SoftwareModule softwareModule) {
|
||||
return artifacts.stream().filter(space -> space.getSoftwareModule().getId().equals(softwareModule.getId()))
|
||||
.findFirst().get();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getExchange() {
|
||||
return AmqpSettings.AUTHENTICATION_EXCHANGE;
|
||||
}
|
||||
|
||||
private int getAuthenticationMessageCount() {
|
||||
return Integer.parseInt(getRabbitAdmin().getQueueProperties(amqpProperties.getAuthenticationReceiverQueue())
|
||||
.get(RabbitAdmin.QUEUE_MESSAGE_COUNT).toString());
|
||||
}
|
||||
|
||||
private void assertEmptyAuthenticationMessageCount() {
|
||||
assertThat(getAuthenticationMessageCount()).isEqualTo(0);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user