-
-
Notifications
You must be signed in to change notification settings - Fork 99
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add PGP extension project with file value processing capabilities
- Loading branch information
Stephane Royer
committed
Jan 16, 2025
1 parent
d779259
commit e459b93
Showing
5 changed files
with
236 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
<Import Project="..\SharedSettings.props" /> | ||
<PropertyGroup> | ||
<TargetFramework>netstandard2.1</TargetFramework> | ||
<PackageId>Paillave.EtlNet.Pgp</PackageId> | ||
<PackageTags>ETL .net core SSIS reactive pgp</PackageTags> | ||
<Product>ETL.net PGP extensions</Product> | ||
<Description>Extensions for Etl.Net to handle PGP</Description> | ||
</PropertyGroup> | ||
<ItemGroup> | ||
<ProjectReference Include="..\Paillave.Etl\Paillave.Etl.csproj" /> | ||
</ItemGroup> | ||
<ItemGroup> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<PackageReference Include="PgpCore" Version="6.5.1" /> | ||
</ItemGroup> | ||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
using System.IO; | ||
using Paillave.Etl.Core; | ||
|
||
namespace Paillave.Etl.Pgp | ||
{ | ||
public class PgpFileValue<TMetadata> : FileValueBase<TMetadata> where TMetadata : IFileValueMetadata | ||
{ | ||
private readonly Stream _stream; | ||
private readonly IFileValue _underlyingFileValue; | ||
public override string Name { get; } | ||
public PgpFileValue(Stream stream, string name, TMetadata metadata, IFileValue underlyingFileValue) | ||
: base(metadata) | ||
=> (_stream, Name, _underlyingFileValue) | ||
= (stream, name, underlyingFileValue); | ||
public override Stream GetContent() | ||
{ | ||
var ms = new MemoryStream(); | ||
_stream.Seek(0, SeekOrigin.Begin); | ||
_stream.CopyTo(ms); | ||
ms.Seek(0, SeekOrigin.Begin); | ||
return ms; | ||
} | ||
protected override void DeleteFile() | ||
{ | ||
_underlyingFileValue.Delete(); | ||
} | ||
|
||
public override StreamWithResource OpenContent() | ||
{ | ||
_stream.Seek(0, SeekOrigin.Begin); | ||
return new StreamWithResource(_stream); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Threading; | ||
using Paillave.Etl.Core; | ||
using PgpCore; | ||
|
||
namespace Paillave.Etl.Pgp; | ||
public enum PgpOperation | ||
{ | ||
Encrypt, | ||
EncryptAndSign, | ||
Decrypt, | ||
Sign, | ||
UnSign, | ||
Verify | ||
} | ||
public class PgpAdapterProcessorParameters | ||
{ | ||
public PgpOperation Operation { get; set; } = PgpOperation.Decrypt; | ||
public string? PrivateKey { get; set; } | ||
public string? Passphrase { get; set; } | ||
public string? PublicKey { get; set; } | ||
public bool UseStreamCopy { get; set; } = true; | ||
} | ||
public class PgpFileValueMetadata : FileValueMetadataBase, IFileValueWithDestinationMetadata | ||
{ | ||
public string ParentFileName { get; set; } | ||
public IFileValueMetadata ParentFileMetadata { get; set; } | ||
public Dictionary<string, IEnumerable<Destination>> Destinations { get; set; } | ||
} | ||
public class PgpFileValueProcessor : FileValueProcessorBase<PgpAdapterConnectionParameters, PgpAdapterProcessorParameters> | ||
{ | ||
public PgpFileValueProcessor(string code, string name, string connectionName, PgpAdapterConnectionParameters connectionParameters, PgpAdapterProcessorParameters processorParameters) | ||
: base(code, name, connectionName, connectionParameters, processorParameters) { } | ||
public override ProcessImpact PerformanceImpact => ProcessImpact.Heavy; | ||
public override ProcessImpact MemoryFootPrint => ProcessImpact.Average; | ||
private EncryptionKeys CreateEncryptionKeys(PgpAdapterProcessorParameters processorParameters) | ||
{ | ||
if (!string.IsNullOrWhiteSpace(processorParameters.Passphrase) && !string.IsNullOrWhiteSpace(processorParameters.PublicKey) && !string.IsNullOrWhiteSpace(processorParameters.PrivateKey)) | ||
return new EncryptionKeys(processorParameters.PublicKey, processorParameters.PrivateKey, processorParameters.Passphrase); | ||
else if (!string.IsNullOrWhiteSpace(processorParameters.Passphrase) && !string.IsNullOrWhiteSpace(processorParameters.PrivateKey)) | ||
return new EncryptionKeys(processorParameters.PrivateKey, processorParameters.Passphrase); | ||
else if (!string.IsNullOrWhiteSpace(processorParameters.PublicKey)) | ||
return new EncryptionKeys(processorParameters.PublicKey); | ||
throw new ArgumentException("Missing key parameters"); | ||
} | ||
protected override void Process(IFileValue fileValue, PgpAdapterConnectionParameters connectionParameters, PgpAdapterProcessorParameters processorParameters, Action<IFileValue> push, CancellationToken cancellationToken, IExecutionContext context) | ||
{ | ||
var destinations = (fileValue.Metadata as IFileValueWithDestinationMetadata)?.Destinations; | ||
if (cancellationToken.IsCancellationRequested) return; | ||
using var inputStream = fileValue.Get(processorParameters.UseStreamCopy); | ||
|
||
switch (processorParameters.Operation) | ||
{ | ||
case PgpOperation.Decrypt: | ||
{ | ||
var encryptionKeys = CreateEncryptionKeys(processorParameters); | ||
var pgp = new PGP(encryptionKeys); | ||
var ms = new MemoryStream(); | ||
pgp.Decrypt(inputStream, ms); | ||
ms.Seek(0, SeekOrigin.Begin); | ||
push(new PgpFileValue<PgpFileValueMetadata>(ms, fileValue.Name, new PgpFileValueMetadata | ||
{ | ||
ParentFileName = fileValue.Name, | ||
ParentFileMetadata = fileValue.Metadata, | ||
Destinations = destinations | ||
}, fileValue)); | ||
} | ||
break; | ||
case PgpOperation.Encrypt: | ||
{ | ||
var encryptionKeys = CreateEncryptionKeys(processorParameters); | ||
var pgp = new PGP(encryptionKeys); | ||
var ms = new MemoryStream(); | ||
pgp.Encrypt(inputStream, ms); | ||
ms.Seek(0, SeekOrigin.Begin); | ||
push(new PgpFileValue<PgpFileValueMetadata>(ms, fileValue.Name, new PgpFileValueMetadata | ||
{ | ||
ParentFileName = fileValue.Name, | ||
ParentFileMetadata = fileValue.Metadata, | ||
Destinations = destinations | ||
}, fileValue)); | ||
} | ||
break; | ||
case PgpOperation.Sign: | ||
{ | ||
var encryptionKeys = CreateEncryptionKeys(processorParameters); | ||
var pgp = new PGP(encryptionKeys); | ||
var ms = new MemoryStream(); | ||
pgp.Sign(inputStream, ms); | ||
ms.Seek(0, SeekOrigin.Begin); | ||
push(new PgpFileValue<PgpFileValueMetadata>(ms, fileValue.Name, new PgpFileValueMetadata | ||
{ | ||
ParentFileName = fileValue.Name, | ||
ParentFileMetadata = fileValue.Metadata, | ||
Destinations = destinations | ||
}, fileValue)); | ||
} | ||
break; | ||
case PgpOperation.EncryptAndSign: | ||
{ | ||
var encryptionKeys = CreateEncryptionKeys(processorParameters); | ||
var pgp = new PGP(encryptionKeys); | ||
var ms = new MemoryStream(); | ||
pgp.EncryptAndSign(inputStream, ms); | ||
ms.Seek(0, SeekOrigin.Begin); | ||
push(new PgpFileValue<PgpFileValueMetadata>(ms, fileValue.Name, new PgpFileValueMetadata | ||
{ | ||
ParentFileName = fileValue.Name, | ||
ParentFileMetadata = fileValue.Metadata, | ||
Destinations = destinations | ||
}, fileValue)); | ||
} | ||
break; | ||
case PgpOperation.UnSign: | ||
{ | ||
var encryptionKeys = CreateEncryptionKeys(processorParameters); | ||
var pgp = new PGP(encryptionKeys); | ||
var ms = new MemoryStream(); | ||
pgp.ClearSign(inputStream, ms); | ||
ms.Seek(0, SeekOrigin.Begin); | ||
push(new PgpFileValue<PgpFileValueMetadata>(ms, fileValue.Name, new PgpFileValueMetadata | ||
{ | ||
ParentFileName = fileValue.Name, | ||
ParentFileMetadata = fileValue.Metadata, | ||
Destinations = destinations | ||
}, fileValue)); | ||
} | ||
break; | ||
case PgpOperation.Verify: | ||
{ | ||
var encryptionKeys = CreateEncryptionKeys(processorParameters); | ||
var pgp = new PGP(encryptionKeys); | ||
var ms = new MemoryStream(); | ||
var verified = pgp.Verify(inputStream, ms); | ||
if (verified) | ||
{ | ||
ms.Seek(0, SeekOrigin.Begin); | ||
push(new PgpFileValue<PgpFileValueMetadata>(ms, fileValue.Name, new PgpFileValueMetadata | ||
{ | ||
ParentFileName = fileValue.Name, | ||
ParentFileMetadata = fileValue.Metadata, | ||
Destinations = destinations | ||
}, fileValue)); | ||
} | ||
} | ||
break; | ||
} | ||
} | ||
|
||
protected override void Test(PgpAdapterConnectionParameters connectionParameters, PgpAdapterProcessorParameters processorParameters) { } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
using Paillave.Etl.Core; | ||
|
||
namespace Paillave.Etl.Pgp; | ||
|
||
public class PgpAdapterConnectionParameters | ||
{ | ||
} | ||
|
||
public class PgpProviderProcessorAdapter : ProviderProcessorAdapterBase<PgpAdapterConnectionParameters, object, PgpAdapterProcessorParameters> | ||
{ | ||
public override string Description => "Handle zip files"; | ||
public override string Name => "Zip"; | ||
protected override IFileValueProvider CreateProvider(string code, string name, string connectionName, PgpAdapterConnectionParameters connectionParameters, object inputParameters) | ||
=> null; | ||
protected override IFileValueProcessor CreateProcessor(string code, string name, string connectionName, PgpAdapterConnectionParameters connectionParameters, PgpAdapterProcessorParameters outputParameters) | ||
=> new PgpFileValueProcessor(code, name, connectionName, connectionParameters, outputParameters); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters