Feature/enforce hash validation for uploads (#1158)
* moved artifact duplication check after hash check Signed-off-by: Robert Sing <robert.sing@bosch-si.com> * added unit tests Signed-off-by: Robert Sing <robert.sing@bosch-si.com> * fixed copyright header Signed-off-by: Robert Sing <robert.sing@bosch-si.com> * fixed review finding Signed-off-by: Robert Sing <robert.sing@bosch-si.com>
This commit is contained in:
@@ -55,9 +55,9 @@ public abstract class AbstractArtifactRepository implements ArtifactRepository {
|
||||
}
|
||||
|
||||
String tempFile = null;
|
||||
try (final DigestInputStream inputstream = wrapInDigestInputStream(content, mdSHA1, mdMD5, mdSHA256)) {
|
||||
try (final DigestInputStream inputStream = wrapInDigestInputStream(content, mdSHA1, mdMD5, mdSHA256)) {
|
||||
|
||||
tempFile = storeTempFile(inputstream);
|
||||
tempFile = storeTempFile(inputStream);
|
||||
|
||||
final String sha1Hash16 = BaseEncoding.base16().lowerCase().encode(mdSHA1.digest());
|
||||
final String md5Hash16 = BaseEncoding.base16().lowerCase().encode(mdMD5.digest());
|
||||
@@ -65,6 +65,11 @@ public abstract class AbstractArtifactRepository implements ArtifactRepository {
|
||||
|
||||
checkHashes(sha1Hash16, md5Hash16, sha256Hash16, providedHashes);
|
||||
|
||||
// Check if file with same sha1 hash exists and if so return it
|
||||
if (existsByTenantAndSha1(tenant, sha1Hash16)) {
|
||||
return addMissingHashes(getArtifactBySha1(tenant, sha1Hash16), sha1Hash16, md5Hash16, sha256Hash16);
|
||||
}
|
||||
|
||||
return store(sanitizeTenant(tenant), new DbArtifactHash(sha1Hash16, md5Hash16, sha256Hash16), contentType,
|
||||
tempFile);
|
||||
} catch (final IOException e) {
|
||||
@@ -76,6 +81,21 @@ public abstract class AbstractArtifactRepository implements ArtifactRepository {
|
||||
}
|
||||
}
|
||||
|
||||
private AbstractDbArtifact addMissingHashes(final AbstractDbArtifact existing, final String calculatedSha1,
|
||||
final String calculatedMd5, final String calculatedSha256) {
|
||||
|
||||
final String sha1 = checkEmpty(existing.getHashes().getSha1(), calculatedSha1);
|
||||
final String md5 = checkEmpty(existing.getHashes().getMd5(), calculatedMd5);
|
||||
final String sha256 = checkEmpty(existing.getHashes().getSha256(), calculatedSha256);
|
||||
|
||||
existing.setHashes(new DbArtifactHash(sha1, md5, sha256));
|
||||
return existing;
|
||||
}
|
||||
|
||||
private String checkEmpty(final String value, final String fallback) {
|
||||
return StringUtils.isEmpty(value) ? fallback : value;
|
||||
}
|
||||
|
||||
protected void deleteTempFile(final String tempFile) {
|
||||
final File file = new File(tempFile);
|
||||
|
||||
@@ -118,12 +138,14 @@ public abstract class AbstractArtifactRepository implements ArtifactRepository {
|
||||
+ " does not match the calculated md5 hash " + md5Hash16, HashNotMatchException.MD5);
|
||||
}
|
||||
if (areHashesNotMatching(providedHashes.getSha256(), sha256Hash16)) {
|
||||
throw new HashNotMatchException("The given sha256 hash " + providedHashes.getSha256()
|
||||
+ " does not match the calculated sha256 hash " + sha256Hash16, HashNotMatchException.SHA256);
|
||||
throw new HashNotMatchException(
|
||||
"The given sha256 hash " + providedHashes.getSha256()
|
||||
+ " does not match the calculated sha256 hash " + sha256Hash16,
|
||||
HashNotMatchException.SHA256);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean areHashesNotMatching(String providedHashValue, String hashValue) {
|
||||
private static boolean areHashesNotMatching(final String providedHashValue, final String hashValue) {
|
||||
return providedHashValue != null && !hashValue.equals(providedHashValue);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,10 +19,11 @@ import org.springframework.util.Assert;
|
||||
public abstract class AbstractDbArtifact {
|
||||
|
||||
private final String artifactId;
|
||||
private final DbArtifactHash hashes;
|
||||
private final long size;
|
||||
private final String contentType;
|
||||
|
||||
private DbArtifactHash hashes;
|
||||
|
||||
protected AbstractDbArtifact(final String artifactId, final DbArtifactHash hashes, final long size,
|
||||
final String contentType) {
|
||||
Assert.notNull(artifactId, "Artifact ID cannot be null");
|
||||
@@ -47,6 +48,13 @@ public abstract class AbstractDbArtifact {
|
||||
return hashes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set hashes of the artifact
|
||||
*/
|
||||
public void setHashes(final DbArtifactHash hashes) {
|
||||
this.hashes = hashes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return site of the artifact in bytes
|
||||
*/
|
||||
@@ -62,8 +70,8 @@ public abstract class AbstractDbArtifact {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an {@link InputStream} on this artifact. Caller has to take care
|
||||
* of closing the stream. Repeatable calls open a new {@link InputStream}.
|
||||
* Creates an {@link InputStream} on this artifact. Caller has to take care of
|
||||
* closing the stream. Repeatable calls open a new {@link InputStream}.
|
||||
*
|
||||
* @return {@link InputStream} to read from artifact.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user