mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-06 21:00:22 +00:00
Merge pull request #7837 from gdicristofaro/AUT-2459-fileUpload
AUT-2459 file upload changes
This commit is contained in:
commit
aa38ccb832
@ -25,6 +25,7 @@ import com.basistech.df.cybertriage.autopsy.ctapi.json.CTCloudBean;
|
|||||||
import com.basistech.df.cybertriage.autopsy.ctapi.json.CTCloudBeanResponse;
|
import com.basistech.df.cybertriage.autopsy.ctapi.json.CTCloudBeanResponse;
|
||||||
import com.basistech.df.cybertriage.autopsy.ctapi.json.DecryptedLicenseResponse;
|
import com.basistech.df.cybertriage.autopsy.ctapi.json.DecryptedLicenseResponse;
|
||||||
import com.basistech.df.cybertriage.autopsy.ctapi.json.FileReputationRequest;
|
import com.basistech.df.cybertriage.autopsy.ctapi.json.FileReputationRequest;
|
||||||
|
import com.basistech.df.cybertriage.autopsy.ctapi.json.FileUploadRequest;
|
||||||
import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseRequest;
|
import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseRequest;
|
||||||
import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseResponse;
|
import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseResponse;
|
||||||
import com.basistech.df.cybertriage.autopsy.ctapi.json.MetadataUploadRequest;
|
import com.basistech.df.cybertriage.autopsy.ctapi.json.MetadataUploadRequest;
|
||||||
@ -78,21 +79,22 @@ public class CTApiDAO {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public AuthTokenResponse getAuthToken(DecryptedLicenseResponse decrypted) throws CTCloudException {
|
public AuthTokenResponse getAuthToken(DecryptedLicenseResponse decrypted) throws CTCloudException {
|
||||||
return getAuthToken(decrypted, false);
|
return getAuthToken(decrypted, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AuthTokenResponse getAuthToken(DecryptedLicenseResponse decrypted, boolean fileUpload) throws CTCloudException {
|
public AuthTokenResponse getAuthToken(DecryptedLicenseResponse decrypted, Long fileUploadSize) throws CTCloudException {
|
||||||
AuthTokenRequest authTokenRequest = new AuthTokenRequest()
|
AuthTokenRequest authTokenRequest = new AuthTokenRequest()
|
||||||
.setAutopsyVersion(getAppVersion())
|
.setAutopsyVersion(getAppVersion())
|
||||||
.setRequestFileUpload(fileUpload)
|
.setRequestFileUpload(fileUploadSize != null && fileUploadSize > 0)
|
||||||
|
.setFileUploadSize(fileUploadSize != null && fileUploadSize > 0 ? fileUploadSize : null)
|
||||||
.setBoostLicenseId(decrypted.getBoostLicenseId())
|
.setBoostLicenseId(decrypted.getBoostLicenseId())
|
||||||
.setHostId(decrypted.getLicenseHostId());
|
.setHostId(decrypted.getLicenseHostId());
|
||||||
|
|
||||||
return httpClient.doPost(AUTH_TOKEN_REQUEST_PATH, authTokenRequest, AuthTokenResponse.class);
|
return httpClient.doPost(AUTH_TOKEN_REQUEST_PATH, authTokenRequest, AuthTokenResponse.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void uploadFile(String url, String fileName, InputStream fileIs) throws CTCloudException {
|
public void uploadFile(FileUploadRequest fileUploadRequest) throws CTCloudException {
|
||||||
httpClient.doFileUploadPost(url, fileName, fileIs);
|
httpClient.doFileUploadPut(fileUploadRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void uploadMeta(AuthenticatedRequestData authenticatedRequestData, MetadataUploadRequest metaRequest) throws CTCloudException {
|
public void uploadMeta(AuthenticatedRequestData authenticatedRequestData, MetadataUploadRequest metaRequest) throws CTCloudException {
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
*/
|
*/
|
||||||
package com.basistech.df.cybertriage.autopsy.ctapi;
|
package com.basistech.df.cybertriage.autopsy.ctapi;
|
||||||
|
|
||||||
|
import com.basistech.df.cybertriage.autopsy.ctapi.CTCloudException.ErrorCode;
|
||||||
|
import com.basistech.df.cybertriage.autopsy.ctapi.json.FileUploadRequest;
|
||||||
import com.basistech.df.cybertriage.autopsy.ctapi.util.ObjectMapperUtil;
|
import com.basistech.df.cybertriage.autopsy.ctapi.util.ObjectMapperUtil;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -55,13 +57,14 @@ import org.apache.http.HttpStatus;
|
|||||||
import org.apache.http.client.config.RequestConfig;
|
import org.apache.http.client.config.RequestConfig;
|
||||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
import org.apache.http.client.methods.HttpPost;
|
import org.apache.http.client.methods.HttpPost;
|
||||||
|
import org.apache.http.client.methods.HttpPut;
|
||||||
import org.apache.http.client.methods.HttpRequestBase;
|
import org.apache.http.client.methods.HttpRequestBase;
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
import org.apache.http.util.EntityUtils;
|
import org.apache.http.util.EntityUtils;
|
||||||
import org.apache.http.client.utils.URIBuilder;
|
import org.apache.http.client.utils.URIBuilder;
|
||||||
import org.apache.http.entity.ContentType;
|
import org.apache.http.entity.ContentType;
|
||||||
|
import org.apache.http.entity.InputStreamEntity;
|
||||||
import org.apache.http.entity.StringEntity;
|
import org.apache.http.entity.StringEntity;
|
||||||
import org.apache.http.entity.mime.MultipartEntityBuilder;
|
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.apache.http.impl.client.HttpClientBuilder;
|
import org.apache.http.impl.client.HttpClientBuilder;
|
||||||
import org.apache.http.impl.client.HttpClients;
|
import org.apache.http.impl.client.HttpClients;
|
||||||
@ -184,10 +187,23 @@ class CTCloudHttpClient {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void doFileUploadPost(String fullUrlPath, String fileName, InputStream fileIs) throws CTCloudException {
|
public void doFileUploadPut(FileUploadRequest fileUploadRequest) throws CTCloudException {
|
||||||
URI postUri;
|
if (fileUploadRequest == null) {
|
||||||
|
throw new CTCloudException(ErrorCode.BAD_REQUEST, new IllegalArgumentException("fileUploadRequest cannot be null"));
|
||||||
|
}
|
||||||
|
|
||||||
|
String fullUrlPath = fileUploadRequest.getFullUrlPath();
|
||||||
|
String fileName = fileUploadRequest.getFileName();
|
||||||
|
InputStream fileInputStream = fileUploadRequest.getFileInputStream();
|
||||||
|
Long contentLength = fileUploadRequest.getContentLength();
|
||||||
|
|
||||||
|
if (StringUtils.isBlank(fullUrlPath) || fileInputStream == null || contentLength == null || contentLength <= 0) {
|
||||||
|
throw new CTCloudException(ErrorCode.BAD_REQUEST, new IllegalArgumentException("fullUrlPath, fileInputStream, contentLength must not be empty, null or less than 0"));
|
||||||
|
}
|
||||||
|
|
||||||
|
URI putUri;
|
||||||
try {
|
try {
|
||||||
postUri = new URI(fullUrlPath);
|
putUri = new URI(fullUrlPath);
|
||||||
} catch (URISyntaxException ex) {
|
} catch (URISyntaxException ex) {
|
||||||
LOGGER.log(Level.WARNING, "Wrong URL syntax for CT Cloud " + fullUrlPath, ex);
|
LOGGER.log(Level.WARNING, "Wrong URL syntax for CT Cloud " + fullUrlPath, ex);
|
||||||
throw new CTCloudException(CTCloudException.ErrorCode.UNKNOWN, ex);
|
throw new CTCloudException(CTCloudException.ErrorCode.UNKNOWN, ex);
|
||||||
@ -195,23 +211,13 @@ class CTCloudHttpClient {
|
|||||||
|
|
||||||
try (CloseableHttpClient httpclient = createConnection(proxySelector, sslContext)) {
|
try (CloseableHttpClient httpclient = createConnection(proxySelector, sslContext)) {
|
||||||
LOGGER.log(Level.INFO, "initiating http post request to ctcloud server " + fullUrlPath);
|
LOGGER.log(Level.INFO, "initiating http post request to ctcloud server " + fullUrlPath);
|
||||||
HttpPost post = new HttpPost(postUri);
|
HttpPut put = new HttpPut(putUri);
|
||||||
configureRequestTimeout(post);
|
configureRequestTimeout(put);
|
||||||
|
|
||||||
post.addHeader("Connection", "keep-alive");
|
put.addHeader("Connection", "keep-alive");
|
||||||
|
put.setEntity(new InputStreamEntity(fileInputStream, contentLength, ContentType.APPLICATION_OCTET_STREAM));
|
||||||
|
|
||||||
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
|
try (CloseableHttpResponse response = httpclient.execute(put)) {
|
||||||
builder.addBinaryBody(
|
|
||||||
"file",
|
|
||||||
fileIs,
|
|
||||||
ContentType.APPLICATION_OCTET_STREAM,
|
|
||||||
fileName
|
|
||||||
);
|
|
||||||
|
|
||||||
HttpEntity multipart = builder.build();
|
|
||||||
post.setEntity(multipart);
|
|
||||||
|
|
||||||
try (CloseableHttpResponse response = httpclient.execute(post)) {
|
|
||||||
int statusCode = response.getStatusLine().getStatusCode();
|
int statusCode = response.getStatusLine().getStatusCode();
|
||||||
if (statusCode == HttpStatus.SC_OK || statusCode == HttpStatus.SC_NO_CONTENT) {
|
if (statusCode == HttpStatus.SC_OK || statusCode == HttpStatus.SC_NO_CONTENT) {
|
||||||
LOGGER.log(Level.INFO, "Response Received. - Status OK");
|
LOGGER.log(Level.INFO, "Response Received. - Status OK");
|
||||||
@ -381,7 +387,7 @@ class CTCloudHttpClient {
|
|||||||
HttpClientBuilder builder;
|
HttpClientBuilder builder;
|
||||||
|
|
||||||
if (ProxySettings.getProxyType() != ProxySettings.DIRECT_CONNECTION
|
if (ProxySettings.getProxyType() != ProxySettings.DIRECT_CONNECTION
|
||||||
&& StringUtils.isBlank(ProxySettings.getAuthenticationUsername())
|
&& StringUtils.isBlank(ProxySettings.getAuthenticationUsername())
|
||||||
&& ArrayUtils.isEmpty(ProxySettings.getAuthenticationPassword())
|
&& ArrayUtils.isEmpty(ProxySettings.getAuthenticationPassword())
|
||||||
&& WinHttpClients.isWinAuthAvailable()) {
|
&& WinHttpClients.isWinAuthAvailable()) {
|
||||||
|
|
||||||
|
@ -34,6 +34,9 @@ public class AuthTokenRequest {
|
|||||||
@JsonProperty("requestFileUpload")
|
@JsonProperty("requestFileUpload")
|
||||||
private boolean requestFileUpload;
|
private boolean requestFileUpload;
|
||||||
|
|
||||||
|
@JsonProperty("fileUploadSize")
|
||||||
|
private Long fileUploadSize;
|
||||||
|
|
||||||
@JsonProperty("host_id")
|
@JsonProperty("host_id")
|
||||||
private String hostId;
|
private String hostId;
|
||||||
|
|
||||||
@ -64,6 +67,16 @@ public class AuthTokenRequest {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Long getFileUploadSize() {
|
||||||
|
return fileUploadSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthTokenRequest setFileUploadSize(Long fileUploadSize) {
|
||||||
|
this.fileUploadSize = fileUploadSize;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public String getHostId() {
|
public String getHostId() {
|
||||||
return hostId;
|
return hostId;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2023 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.basistech.df.cybertriage.autopsy.ctapi.json;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data for a file upload request.
|
||||||
|
*/
|
||||||
|
public class FileUploadRequest {
|
||||||
|
|
||||||
|
private String fullUrlPath;
|
||||||
|
private String fileName;
|
||||||
|
private InputStream fileInputStream;
|
||||||
|
private Long contentLength;
|
||||||
|
|
||||||
|
public String getFullUrlPath() {
|
||||||
|
return fullUrlPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileUploadRequest setFullUrlPath(String fullUrlPath) {
|
||||||
|
this.fullUrlPath = fullUrlPath;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFileName() {
|
||||||
|
return fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileUploadRequest setFileName(String fileName) {
|
||||||
|
this.fileName = fileName;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream getFileInputStream() {
|
||||||
|
return fileInputStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileUploadRequest setFileInputStream(InputStream fileInputStream) {
|
||||||
|
this.fileInputStream = fileInputStream;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getContentLength() {
|
||||||
|
return contentLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileUploadRequest setContentLength(Long contentLength) {
|
||||||
|
this.contentLength = contentLength;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -23,6 +23,7 @@ import com.basistech.df.cybertriage.autopsy.ctapi.CTCloudException;
|
|||||||
import com.basistech.df.cybertriage.autopsy.ctapi.json.AuthTokenResponse;
|
import com.basistech.df.cybertriage.autopsy.ctapi.json.AuthTokenResponse;
|
||||||
import com.basistech.df.cybertriage.autopsy.ctapi.json.AuthenticatedRequestData;
|
import com.basistech.df.cybertriage.autopsy.ctapi.json.AuthenticatedRequestData;
|
||||||
import com.basistech.df.cybertriage.autopsy.ctapi.json.CTCloudBean;
|
import com.basistech.df.cybertriage.autopsy.ctapi.json.CTCloudBean;
|
||||||
|
import com.basistech.df.cybertriage.autopsy.ctapi.json.FileUploadRequest;
|
||||||
import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseInfo;
|
import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseInfo;
|
||||||
import com.basistech.df.cybertriage.autopsy.ctapi.json.MalwareResultBean.Status;
|
import com.basistech.df.cybertriage.autopsy.ctapi.json.MalwareResultBean.Status;
|
||||||
import com.basistech.df.cybertriage.autopsy.ctapi.json.MetadataUploadRequest;
|
import com.basistech.df.cybertriage.autopsy.ctapi.json.MetadataUploadRequest;
|
||||||
@ -112,8 +113,10 @@ class MalwareScanIngestModule implements FileIngestModule {
|
|||||||
//minimum file uploads left before issuing warning
|
//minimum file uploads left before issuing warning
|
||||||
private static final long LOW_UPLOADS_REMAINING = 25;
|
private static final long LOW_UPLOADS_REMAINING = 25;
|
||||||
|
|
||||||
|
// min and max upload size in bytes
|
||||||
private static final long MIN_UPLOAD_SIZE = 1;
|
private static final long MIN_UPLOAD_SIZE = 1;
|
||||||
private static final long MAX_UPLOAD_SIZE = 1_000_000_000;
|
private static final long MAX_UPLOAD_SIZE = 100_000_000; // 100MB
|
||||||
|
|
||||||
private static final int NUM_FILE_UPLOAD_RETRIES = 7;
|
private static final int NUM_FILE_UPLOAD_RETRIES = 7;
|
||||||
private static final long FILE_UPLOAD_RETRY_SLEEP_MILLIS = 60 * 1000;
|
private static final long FILE_UPLOAD_RETRY_SLEEP_MILLIS = 60 * 1000;
|
||||||
|
|
||||||
@ -640,7 +643,7 @@ class MalwareScanIngestModule implements FileIngestModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get auth token / file upload url
|
// get auth token / file upload url
|
||||||
AuthTokenResponse authTokenResponse = ctApiDAO.getAuthToken(ingestJobState.getLicenseInfo().getDecryptedLicense(), true);
|
AuthTokenResponse authTokenResponse = ctApiDAO.getAuthToken(ingestJobState.getLicenseInfo().getDecryptedLicense(), af.getSize());
|
||||||
if (StringUtils.isBlank(authTokenResponse.getFileUploadUrl())) {
|
if (StringUtils.isBlank(authTokenResponse.getFileUploadUrl())) {
|
||||||
throw new CTCloudException(CTCloudException.ErrorCode.NETWORK_ERROR);
|
throw new CTCloudException(CTCloudException.ErrorCode.NETWORK_ERROR);
|
||||||
} else if (remaining(authTokenResponse.getFileUploadLimit(), authTokenResponse.getFileUploadCount()) <= 0) {
|
} else if (remaining(authTokenResponse.getFileUploadLimit(), authTokenResponse.getFileUploadCount()) <= 0) {
|
||||||
@ -658,7 +661,13 @@ class MalwareScanIngestModule implements FileIngestModule {
|
|||||||
|
|
||||||
// upload bytes
|
// upload bytes
|
||||||
ReadContentInputStream fileInputStream = new ReadContentInputStream(af);
|
ReadContentInputStream fileInputStream = new ReadContentInputStream(af);
|
||||||
ctApiDAO.uploadFile(authTokenResponse.getFileUploadUrl(), af.getName(), fileInputStream);
|
|
||||||
|
ctApiDAO.uploadFile(new FileUploadRequest()
|
||||||
|
.setContentLength(af.getSize())
|
||||||
|
.setFileInputStream(fileInputStream)
|
||||||
|
.setFileName(af.getName())
|
||||||
|
.setFullUrlPath(authTokenResponse.getFileUploadUrl())
|
||||||
|
);
|
||||||
|
|
||||||
// upload metadata
|
// upload metadata
|
||||||
MetadataUploadRequest metaRequest = new MetadataUploadRequest()
|
MetadataUploadRequest metaRequest = new MetadataUploadRequest()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user