Skip to content

Commit

Permalink
[ROAD-1111] Encryption error workaround (#207)
Browse files Browse the repository at this point in the history
  • Loading branch information
Asaf Agami authored Aug 24, 2022
1 parent 300eea5 commit d50f65e
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 22 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## [1.1.26]

### Fixed
- Bug in Snyk Code messages encoding resulting in failed Snyk Code scans.

### Changed
- Update wording in settings menu for collecting analytics.

Expand Down
31 changes: 24 additions & 7 deletions Snyk.Code.Library/Api/Encoding/Encoder.cs
Original file line number Diff line number Diff line change
@@ -1,33 +1,50 @@
namespace Snyk.Code.Library.Api.Encoding
{
using System;
using System.IO;
using System.IO.Compression;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Serilog;
using Snyk.Common;

/// <summary>
/// Snyk Code API requests encoder.
/// </summary>
public class Encoder
{
private static readonly ILogger Logger = LogManager.ForContext<Encoder>();

/// <summary>
/// Encodes payload to base64 and encrypts using Gzip compression.
/// </summary>
/// <param name="payload">content payload to be encoded</param>
/// <returns>Encoded stream</returns>
public static async Task<MemoryStream> EncodeAndCompressAsync(string payload)
{
var destinationPayload = new MemoryStream();
try
{
var destinationPayload = new MemoryStream();

using (var originalPayload = new MemoryStream(Encoding.UTF8.GetBytes(payload)))
using (var compressor = new GZipStream(destinationPayload, CompressionMode.Compress, true))
using (var base64Stream = new CryptoStream(compressor, new ToBase64Transform(), CryptoStreamMode.Write))
{
await Task.Run(() => originalPayload.CopyTo(base64Stream));

using (var originalPayload = new MemoryStream(Encoding.UTF8.GetBytes(payload)))
using (var compressor = new GZipStream(destinationPayload, CompressionMode.Compress, true))
using (var base64Stream = new CryptoStream(compressor, new ToBase64Transform(), CryptoStreamMode.Write))
// Some rare errors about multiple async readers might be related to the next line.
// Removing it for now and using the blocking copy wrapped in a Task.Run()
// await originalPayload.CopyToAsync(base64Stream);
}

return destinationPayload;
}
catch (Exception exception)
{
await originalPayload.CopyToAsync(base64Stream);
Logger.Error(exception, "Error when trying to compress and encrypt payload");
throw;
}

return destinationPayload;
}
}
}
9 changes: 7 additions & 2 deletions Snyk.Code.Library/Api/SnykCodeClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class SnykCodeClient : ISnykCodeClient
/// <summary>
/// Maximum bundle size per one upload is 4 Mb. 4 Mb in bytes.
/// </summary>
public const int MaxBundleSize = 4000000;
public const int MaxBundleSize = 4_000_000;

private const string FiltersApiUrl = "filters";

Expand Down Expand Up @@ -269,10 +269,15 @@ private async Task<HttpContent> NewHttpRequestContentAsync(HttpMethod method, st
// Snyk Code PUT and POST requests must be base64 encoded and deflated for certain environments (ROAD-909)
if (method == HttpMethod.Put || method == HttpMethod.Post)
{
Logger.Information("Encoding and compressing {Length} bytes...", System.Text.Encoding.UTF8.GetByteCount(payload));
var encodedPayload = await Encoder.EncodeAndCompressAsync(payload);
return new ByteArrayContent(encodedPayload.ToArray());
var byteContent = encodedPayload.ToArray();
Logger.Information("Sending {Length} bytes", byteContent.Length);

return new ByteArrayContent(byteContent);
}

Logger.Information("Sending {Length} bytes...", System.Text.Encoding.UTF8.GetByteCount(payload));
return new StringContent(payload, System.Text.Encoding.UTF8, "application/json");
}
}
Expand Down
2 changes: 1 addition & 1 deletion Snyk.Code.Library/Service/AnalysisService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ private async Task<AnalysisResultDto> TryGetAnalysisDtoAsync(
int requestAttempts,
CancellationToken cancellationToken = default)
{
Logger.Debug("Try get analysis DTO object {RequestAttempts} times.", RequestAttempts);
Logger.Debug("Try get analysis DTO object {RequestAttempts} times.", requestAttempts);

cancellationToken.ThrowIfCancellationRequested();

Expand Down
21 changes: 13 additions & 8 deletions Snyk.Code.Library/Service/BundleService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ public async Task<bool> UploadFilesAsync(

fireScanCodeProgressUpdate(SnykCodeScanState.Preparing, 100);

return bundle.MissingFiles.Count() == 0;
return !bundle.MissingFiles.Any();
}
else
{
Expand Down Expand Up @@ -315,12 +315,17 @@ public List<Dictionary<string, string>> SplitFilesToChunkListsBySize(

foreach (var filePair in pathToHashFileDict)
{
cancellationToken.ThrowIfCancellationRequested();

int fileSize = this.CalculateFilePairSize(filePair);
var filename = filePair.Key;

cancellationToken.ThrowIfCancellationRequested();
var fileSize = this.CalculateFilePairSize(filePair);
if (fileSize > maxChunkSize)
{
Logger.Information(
"Skipping file {Filename} because it's size is larger than the Snyk Code limit ({FileSize} > {MaxChunkSize})",
filename,
fileSize,
maxChunkSize);
continue; // If file too big it skip it and continue to upload other files.
}

Expand All @@ -334,7 +339,7 @@ public List<Dictionary<string, string>> SplitFilesToChunkListsBySize(
bundleSize = 0;
}

fileDictionary.Add(filePair.Key, filePair.Value);
fileDictionary.Add(filename, filePair.Value);

bundleSize += fileSize;
}
Expand Down Expand Up @@ -552,20 +557,20 @@ public async Task<BundleResponseDto> ProcessCreateLargeBundleAsync(
private int CalculateFilePairSize(KeyValuePair<string, (string, string)> filePair) => this.CalculatePayloadSize(Json.Serialize(filePair));

/// <summary>
/// Claculate file pairs size.
/// Calculate file pairs size.
/// </summary>
/// <param name="files">Source dictionary with file info.</param>
/// <returns>Size of dictionary.</returns>
private int CalculateFilesSize(IDictionary<string, string> files) => this.CalculatePayloadSize(Json.Serialize(files));

/// <summary>
/// Claculate file pairs size.
/// Calculate file pairs size.
/// </summary>
/// <param name="files">Source dictionary with file info.</param>
private int CalculateFilesSize(IDictionary<string, (string, string)> files) => this.CalculatePayloadSize(Json.Serialize(files));

/// <summary>
/// Claculate file pairs size.
/// Calculate file pairs size.
/// </summary>
/// <param name="files">Source dictionary with file info.</param>
/// <returns>Size of dictionary.</returns>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,9 +174,9 @@ public void CancelTasks()
this.isSnykCodeScanning = false;
this.isCliDownloading = false;

this.CancelTask(this.ossScanTokenSource);
this.CancelTask(this.snykCodeScanTokenSource);
this.CancelTask(this.downloadCliTokenSource);
this.CancelTask(ref this.ossScanTokenSource);
this.CancelTask(ref this.snykCodeScanTokenSource);
this.CancelTask(ref this.downloadCliTokenSource);

this.serviceProvider.OssService.StopScan();
}
Expand Down Expand Up @@ -662,7 +662,7 @@ private IList<AnalysisType> GetSelectedFeatures(FeaturesSettings featuresSetting
return selectedProducts;
}

private void CancelTask(CancellationTokenSource tokenSource)
private void CancelTask(ref CancellationTokenSource tokenSource)
{
try
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ public void InitializeEventListeners(ISnykCodeService codeService, ISnykOptions

private void OnOssScanError(object sender, SnykCliScanEventArgs eventArgs)
{
if (this.options == null || this.statusBar == null)
{
return;
}

if (!this.options.SnykCodeSecurityEnabled && !this.options.SnykCodeQualityEnabled)
{
this.statusBar.ShowSnykCodeUpdateMessage("Snyk Open Source scan error");
Expand Down

0 comments on commit d50f65e

Please sign in to comment.