Artifact Encryption plug point (#1202)
* added ArtifactEncryption interface, injected it into SM creation UI module, added encryption metadata key generation upon SM creation, used encryptor during file upload Signed-off-by: Bogdan Bondar <Bogdan.Bondar@bosch.io> * add default artifact encryption implementation based on gcm aes algorithm Signed-off-by: Bogdan Bondar <Bogdan.Bondar@bosch.io> * changed ArtifactEncryptor interface to manage encryption secrets by itself Signed-off-by: Bogdan Bondar <Bogdan.Bondar@bosch.io> * cleaned up stale code, fixed sonar Signed-off-by: Bogdan Bondar <Bogdan.Bondar@bosch.io> * fixed software module encryption within transaction Signed-off-by: Bogdan Bondar <Bogdan.Bondar@bosch.io> * added artifact encryption secrets store Signed-off-by: Bogdan Bondar <Bogdan.Bondar@bosch.io> * extended ArtifactEncryption interface to allow decryption, secrets store provides removeSecret, added missing javadocs Signed-off-by: Bogdan Bondar <Bogdan.Bondar@bosch.io> * intriduced DbArtifact interface, use EncryptionAwareDbArtifact for artifact decryption during download Signed-off-by: Bogdan Bondar <Bogdan.Bondar@bosch.io> * introduced ArtifactEncryptionService to minimize duplications and unneccessary dependency injections Signed-off-by: Bogdan Bondar <Bogdan.Bondar@bosch.io> * declared ArtifactEncryptionService as a bean Signed-off-by: Bogdan Bondar <Bogdan.Bondar@bosch.io> * added persistant encryption flag to software module Signed-off-by: Bogdan Bondar <Bogdan.Bondar@bosch.io> * further adptations for encryption flag persistence Signed-off-by: Bogdan Bondar <Bogdan.Bondar@bosch.io> * added ArtifactEncryptionException, fixed encryption check in UI Signed-off-by: Bogdan Bondar <Bogdan.Bondar@bosch.io> * added encryption error handling Signed-off-by: Bogdan Bondar <Bogdan.Bondar@bosch.io> * added encrypted flag to DDI/DMF, adapted exception handling Signed-off-by: Bogdan Bondar <Bogdan.Bondar@bosch.io> * adapted rest docs Signed-off-by: Bogdan Bondar <Bogdan.Bondar@bosch.io> * Add test to verify artifact encryption is not given by default Signed-off-by: Florian Ruschbaschan <Florian.Ruschbaschan@bosch.io> * Add isEncrypted() to toString() of JpaSoftwareModule, fix typos Signed-off-by: Florian Ruschbaschan <Florian.Ruschbaschan@bosch.io> * Fix sql migration scripts Signed-off-by: Florian Ruschbaschan <Florian.Ruschbaschan@bosch.io> * Calculate encrypted artifact size by subtract encryption size overhead Signed-off-by: Florian Ruschbaschan <Florian.Ruschbaschan@bosch.io> * publish upload failed without waiting for interuption during UI file upload Signed-off-by: Bogdan Bondar <Bogdan.Bondar@bosch.io> * upgraded cron utils to 9.1.6 Signed-off-by: Bogdan Bondar <Bogdan.Bondar@bosch.io> Co-authored-by: Florian Ruschbaschan <Florian.Ruschbaschan@bosch.io>
This commit is contained in:
@@ -8,6 +8,18 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.amqp;
|
||||
|
||||
import static org.eclipse.hawkbit.repository.RepositoryConstants.MAX_ACTION_COUNT;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.hawkbit.api.ApiType;
|
||||
import org.eclipse.hawkbit.api.ArtifactUrl;
|
||||
import org.eclipse.hawkbit.api.ArtifactUrlHandler;
|
||||
@@ -55,18 +67,6 @@ import org.springframework.context.event.EventListener;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.eclipse.hawkbit.repository.RepositoryConstants.MAX_ACTION_COUNT;
|
||||
|
||||
/**
|
||||
* {@link AmqpMessageDispatcherService} create all outgoing AMQP messages and
|
||||
* delegate the messages to a {@link AmqpMessageSenderService}.
|
||||
@@ -105,8 +105,8 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
|
||||
* @param targetManagement
|
||||
* to access target information
|
||||
* @param serviceMatcher
|
||||
* to check in cluster case if the message is from the same cluster
|
||||
* node
|
||||
* to check in cluster case if the message is from the same
|
||||
* cluster node
|
||||
* @param distributionSetManagement
|
||||
* to retrieve modules
|
||||
*/
|
||||
@@ -129,8 +129,8 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to send a message to a RabbitMQ Exchange after the Distribution set
|
||||
* has been assign to a Target.
|
||||
* Method to send a message to a RabbitMQ Exchange after the Distribution
|
||||
* set has been assign to a Target.
|
||||
*
|
||||
* @param assignedEvent
|
||||
* the object to be send.
|
||||
@@ -257,9 +257,9 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
|
||||
|
||||
/**
|
||||
* Method to get the type of event depending on whether the action is a
|
||||
* DOWNLOAD_ONLY action or if it has a valid maintenance window available or not
|
||||
* based on defined maintenance schedule. In case of no maintenance schedule or
|
||||
* if there is a valid window available, the topic
|
||||
* DOWNLOAD_ONLY action or if it has a valid maintenance window available or
|
||||
* not based on defined maintenance schedule. In case of no maintenance
|
||||
* schedule or if there is a valid window available, the topic
|
||||
* {@link EventTopic#DOWNLOAD_AND_INSTALL} is returned else
|
||||
* {@link EventTopic#DOWNLOAD} is returned.
|
||||
*
|
||||
@@ -275,8 +275,8 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the {@link EventTopic} for the given {@link Action}, depending on
|
||||
* its action type.
|
||||
* Determines the {@link EventTopic} for the given {@link Action}, depending
|
||||
* on its action type.
|
||||
*
|
||||
* @param action
|
||||
* to obtain the corresponding {@link EventTopic} for
|
||||
@@ -291,8 +291,8 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to send a message to a RabbitMQ Exchange after the assignment of the
|
||||
* Distribution set to a Target has been canceled.
|
||||
* Method to send a message to a RabbitMQ Exchange after the assignment of
|
||||
* the Distribution set to a Target has been canceled.
|
||||
*
|
||||
* @param cancelEvent
|
||||
* that is to be converted to a DMF message
|
||||
@@ -315,11 +315,12 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to send a message to a RabbitMQ Exchange after a Target was deleted.
|
||||
* Method to send a message to a RabbitMQ Exchange after a Target was
|
||||
* deleted.
|
||||
*
|
||||
* @param deleteEvent
|
||||
* the TargetDeletedEvent which holds the necessary data for sending
|
||||
* a target delete message.
|
||||
* the TargetDeletedEvent which holds the necessary data for
|
||||
* sending a target delete message.
|
||||
*/
|
||||
@EventListener(classes = TargetDeletedEvent.class)
|
||||
protected void targetDelete(final TargetDeletedEvent deleteEvent) {
|
||||
@@ -345,7 +346,8 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
|
||||
return;
|
||||
}
|
||||
|
||||
final DmfDownloadAndUpdateRequest downloadAndUpdateRequest = createDownloadAndUpdateRequest(target, action.getId(), modules);
|
||||
final DmfDownloadAndUpdateRequest downloadAndUpdateRequest = createDownloadAndUpdateRequest(target,
|
||||
action.getId(), modules);
|
||||
final Message message = getMessageConverter().toMessage(downloadAndUpdateRequest,
|
||||
createConnectorMessagePropertiesEvent(tenant, target.getControllerId(), getEventTypeForTarget(action)));
|
||||
amqpSenderService.sendMessage(message, targetAddress);
|
||||
@@ -445,6 +447,7 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
|
||||
amqpSoftwareModule.setModuleId(entry.getKey().getId());
|
||||
amqpSoftwareModule.setModuleType(entry.getKey().getType().getKey());
|
||||
amqpSoftwareModule.setModuleVersion(entry.getKey().getVersion());
|
||||
amqpSoftwareModule.setEncrypted(entry.getKey().isEncrypted() ? Boolean.TRUE : null);
|
||||
amqpSoftwareModule.setArtifacts(convertArtifacts(target, entry.getKey().getArtifacts()));
|
||||
|
||||
if (!CollectionUtils.isEmpty(entry.getValue())) {
|
||||
|
||||
@@ -150,8 +150,8 @@ public class AmqpControllerAuthenticationTest {
|
||||
|
||||
authenticationManager.postConstruct();
|
||||
|
||||
testArtifact = new JpaArtifact(SHA1, "afilename", new JpaSoftwareModule(
|
||||
new JpaSoftwareModuleType("a key", "a name", null, 1), "a name", null, null, null));
|
||||
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,
|
||||
@@ -260,7 +260,7 @@ public class AmqpControllerAuthenticationTest {
|
||||
|
||||
when(tenantConfigurationManagementMock.getConfigurationValue(
|
||||
eq(TenantConfigurationKey.AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED), eq(Boolean.class)))
|
||||
.thenReturn(CONFIG_VALUE_TRUE);
|
||||
.thenReturn(CONFIG_VALUE_TRUE);
|
||||
|
||||
when(rabbitTemplate.getMessageConverter()).thenReturn(messageConverter);
|
||||
|
||||
|
||||
@@ -32,6 +32,8 @@ public class DmfSoftwareModule {
|
||||
@JsonProperty
|
||||
private String moduleVersion;
|
||||
@JsonProperty
|
||||
private Boolean encrypted;
|
||||
@JsonProperty
|
||||
private List<DmfArtifact> artifacts;
|
||||
@JsonProperty
|
||||
private List<DmfMetadata> metadata;
|
||||
@@ -83,11 +85,18 @@ public class DmfSoftwareModule {
|
||||
}
|
||||
}
|
||||
|
||||
public Boolean getEncrypted() {
|
||||
return encrypted;
|
||||
}
|
||||
|
||||
public void setEncrypted(final Boolean encrypted) {
|
||||
this.encrypted = encrypted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
"DmfSoftwareModule [moduleId=%d, moduleType='%s', moduleVersion='%s', artifacts=%s, metadata=%s]",
|
||||
moduleId, moduleType, moduleVersion, artifacts, metadata);
|
||||
"DmfSoftwareModule [moduleId=%d, moduleType='%s', moduleVersion='%s', encrypted='%s' artifacts=%s, metadata=%s]",
|
||||
moduleId, moduleType, moduleVersion, encrypted, artifacts, metadata);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user