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:
Bondar Bogdan
2021-11-18 09:07:05 +01:00
committed by GitHub
parent 7e28fba104
commit 146735012a
74 changed files with 1214 additions and 324 deletions

View File

@@ -8,14 +8,15 @@
*/
package org.eclipse.hawkbit.rest.exception;
import com.google.common.collect.Iterables;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
@@ -31,6 +32,8 @@ import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.multipart.MultipartException;
import com.google.common.collect.Iterables;
/**
* General controller advice for exception handling.
*/
@@ -54,6 +57,8 @@ public class ResponseExceptionHandler {
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_REST_RSQL_SEARCH_PARAM_SYNTAX, HttpStatus.BAD_REQUEST);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_INSUFFICIENT_PERMISSION, HttpStatus.FORBIDDEN);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ARTIFACT_UPLOAD_FAILED, HttpStatus.INTERNAL_SERVER_ERROR);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ARTIFACT_ENCRYPTION_NOT_SUPPORTED, HttpStatus.BAD_REQUEST);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ARTIFACT_ENCRYPTION_FAILED, HttpStatus.INTERNAL_SERVER_ERROR);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ARTIFACT_UPLOAD_FAILED_SHA1_MATCH, HttpStatus.BAD_REQUEST);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ARTIFACT_UPLOAD_FAILED_SHA256_MATCH, HttpStatus.BAD_REQUEST);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ARTIFACT_UPLOAD_FAILED_MD5_MATCH, HttpStatus.BAD_REQUEST);

View File

@@ -20,7 +20,7 @@ import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.hawkbit.artifact.repository.model.AbstractDbArtifact;
import org.eclipse.hawkbit.artifact.repository.model.DbArtifact;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
@@ -118,9 +118,9 @@ public final class FileStreamingUtil {
* @throws FileStreamingFailedException
* if streaming fails
*/
public static ResponseEntity<InputStream> writeFileResponse(final AbstractDbArtifact artifact,
final String filename, final long lastModified, final HttpServletResponse response,
final HttpServletRequest request, final FileStreamingProgressListener progressListener) {
public static ResponseEntity<InputStream> writeFileResponse(final DbArtifact artifact, final String filename,
final long lastModified, final HttpServletResponse response, final HttpServletRequest request,
final FileStreamingProgressListener progressListener) {
ResponseEntity<InputStream> result;
@@ -189,9 +189,9 @@ public final class FileStreamingUtil {
return result;
}
private static ResponseEntity<InputStream> handleFullFileRequest(final AbstractDbArtifact artifact,
final String filename, final HttpServletResponse response,
final FileStreamingProgressListener progressListener, final ByteRange full) {
private static ResponseEntity<InputStream> handleFullFileRequest(final DbArtifact artifact, final String filename,
final HttpServletResponse response, final FileStreamingProgressListener progressListener,
final ByteRange full) {
final ByteRange r = full;
response.setHeader(HttpHeaders.CONTENT_RANGE, "bytes " + r.getStart() + "-" + r.getEnd() + "/" + r.getTotal());
response.setContentLengthLong(r.getLength());
@@ -257,7 +257,7 @@ public final class FileStreamingUtil {
}
}
private static ResponseEntity<InputStream> handleMultipartRangeRequest(final AbstractDbArtifact artifact,
private static ResponseEntity<InputStream> handleMultipartRangeRequest(final DbArtifact artifact,
final String filename, final HttpServletResponse response,
final FileStreamingProgressListener progressListener, final List<ByteRange> ranges) {
@@ -291,7 +291,7 @@ public final class FileStreamingUtil {
return ResponseEntity.status(HttpStatus.PARTIAL_CONTENT).build();
}
private static ResponseEntity<InputStream> handleStandardRangeRequest(final AbstractDbArtifact artifact,
private static ResponseEntity<InputStream> handleStandardRangeRequest(final DbArtifact artifact,
final String filename, final HttpServletResponse response,
final FileStreamingProgressListener progressListener, final List<ByteRange> ranges) {
final ByteRange r = ranges.get(0);

View File

@@ -97,7 +97,8 @@ public abstract class JsonBuilder {
builder.append(new JSONObject().put("name", module.getName()).put("description", module.getDescription())
.put("type", module.getType().getKey()).put("id", Long.MAX_VALUE).put("vendor", module.getVendor())
.put("version", module.getVersion()).put("createdAt", "0").put("updatedAt", "0")
.put("createdBy", "fghdfkjghdfkjh").put("updatedBy", "fghdfkjghdfkjh").toString());
.put("createdBy", "fghdfkjghdfkjh").put("updatedBy", "fghdfkjghdfkjh")
.put("encrypted", module.isEncrypted()).toString());
if (++i < modules.size()) {
builder.append(",");
@@ -447,7 +448,8 @@ public abstract class JsonBuilder {
return builder.toString();
}
public static String targets(final List<Target> targets, final boolean withToken, final long targetTypeId) throws JSONException {
public static String targets(final List<Target> targets, final boolean withToken, final long targetTypeId)
throws JSONException {
final StringBuilder builder = new StringBuilder();
builder.append("[");
@@ -487,8 +489,8 @@ public abstract class JsonBuilder {
});
result.put(new JSONObject().put("name", type.getName()).put("description", type.getDescription())
.put("id", Long.MAX_VALUE).put("colour", type.getColour()).put("createdAt", "0").put("updatedAt", "0")
.put("createdBy", "fghdfkjghdfkjh").put("updatedBy", "fghdfkjghdfkjh")
.put("id", Long.MAX_VALUE).put("colour", type.getColour()).put("createdAt", "0")
.put("updatedAt", "0").put("createdBy", "fghdfkjghdfkjh").put("updatedBy", "fghdfkjghdfkjh")
.put("distributionsets", dsTypes));
}
@@ -510,11 +512,10 @@ public abstract class JsonBuilder {
}
});
JSONObject json = new JSONObject().put("name", type.getName()).put("description", type.getDescription())
final JSONObject json = new JSONObject().put("name", type.getName()).put("description", type.getDescription())
.put("colour", type.getColour());
if(dsTypes.length() != 0)
{
if (dsTypes.length() != 0) {
json.put("compatibledistributionsettypes", dsTypes);
}