Skip to content

Commit d946099

Browse files
Merge pull request #26 from telerik/mvelikov/cloud-integration
chore: Cloud Integration (Azure & AWS) demos
2 parents 110288b + 39544b5 commit d946099

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+2795
-31
lines changed

.gitignore

Lines changed: 1 addition & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -107,34 +107,4 @@ Generated_Code #added for RIA/Silverlight projects
107107
_UpgradeReport_Files/
108108
Backup*/
109109
UpgradeLog*.XML
110-
/ZipLibrary/.vs
111-
/WordsProcessing/.vs
112-
/SpreadStreamProcessing/.vs
113-
/SpreadProcessing/.vs
114-
/PdfProcessing/.vs
115-
/PdfProcessing/AddWatermark/.vs
116-
/PdfProcessing/CreateDocumentWithImages/.vs
117-
/PdfProcessing/CreateInteractiveForms/.vs
118-
/PdfProcessing/CreatePdfUsingRadFixedDocumentEditor/.vs
119-
/PdfProcessing/DrawHeaderFooter/.vs
120-
/PdfProcessing/ExportUIElement/.vs
121-
/PdfProcessing/GenerateDocument/.vs
122-
/PdfProcessing/ManipulatePages/.vs
123-
/PdfProcessing/ModifyBookmarks/.vs
124-
/PdfProcessing/ModifyForms/.vs
125-
/PdfProcessing/PdfStreamWriterPerformance/.vs
126-
/PdfProcessing/PdfViewerIntegration/.vs
127-
/SpreadProcessing/ConvertDocuments/.vs
128-
/SpreadProcessing/CreateModifyExport/.vs
129-
/SpreadProcessing/ExportChart/.vs
130-
/SpreadProcessing/GenerateDocuments/.vs
131-
/SpreadStreamProcessing/AppendWorksheetToExistingWorkbook/.vs
132-
/SpreadStreamProcessing/GenerateDocument/.vs
133-
/WordsProcessing/ContentControls/.vs
134-
/WordsProcessing/ConvertDocuments/.vs
135-
/WordsProcessing/GenerateDocument/.vs
136-
/WordsProcessing/HtmlGenerator/.vs
137-
/WordsProcessing/MailMerge/.vs
138-
/ZipLibrary/CreateZipArchive/.vs
139-
/ZipLibrary/ExtractZipArchiveToDirectory/.vs
140-
/PdfProcessing/TesseractOcrProviderDemo/.vs
110+
.vs
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
FROM public.ecr.aws/lambda/dotnet:8
2+
3+
WORKDIR /var/task
4+
5+
# This COPY command copies the .NET Lambda project's build artifacts from the host machine into the image.
6+
# The source of the COPY should match where the .NET Lambda project publishes its build artifacts. If the Lambda function is being built
7+
# with the AWS .NET Lambda Tooling, the `--docker-host-build-output-dir` switch controls where the .NET Lambda project
8+
# will be built. The .NET Lambda project templates default to having `--docker-host-build-output-dir`
9+
# set in the aws-lambda-tools-defaults.json file to "bin/Release/lambda-publish".
10+
#
11+
# Alternatively Docker multi-stage build could be used to build the .NET Lambda project inside the image.
12+
# For more information on this approach checkout the project's README.md file.
13+
COPY "bin/Release/lambda-publish" .
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<TargetFramework>net8.0</TargetFramework>
4+
<ImplicitUsings>enable</ImplicitUsings>
5+
<Nullable>enable</Nullable>
6+
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
7+
<AWSProjectType>Lambda</AWSProjectType>
8+
<!-- This property makes the build directory similar to a publish directory and helps the AWS .NET Lambda Mock Test Tool find project dependencies. -->
9+
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
10+
<!-- Generate ready to run images during publishing to improve cold start time. -->
11+
<PublishReadyToRun>true</PublishReadyToRun>
12+
</PropertyGroup>
13+
<ItemGroup>
14+
<PackageReference Include="Amazon.Lambda.Core" Version="*" />
15+
<PackageReference Include="Amazon.Lambda.Serialization.SystemTextJson" Version="*" />
16+
</ItemGroup>
17+
<ItemGroup>
18+
<None Update="Resources\**\*">
19+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
20+
</None>
21+
</ItemGroup>
22+
</Project>
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
using Amazon.Lambda.Core;
2+
using System.Security.Cryptography;
3+
using System.Security.Cryptography.X509Certificates;
4+
5+
// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
6+
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
7+
8+
namespace ExternalSignAWSFunctionApp;
9+
10+
/// <summary>
11+
/// AWS Lambda function that performs digital signature operations for PDF documents.
12+
/// </summary>
13+
public class Function
14+
{
15+
/// <summary>
16+
/// Handler for Lambda function invocations.
17+
/// This method receives data to be signed, signs it using a private key certificate,
18+
/// and returns the Base64-encoded signature.
19+
/// </summary>
20+
/// <param name="input">The input containing the data to sign and digest algorithm.</param>
21+
/// <param name="context">The Lambda execution context.</param>
22+
/// <returns>A Base64-encoded string representing the digital signature.</returns>
23+
/// <exception cref="InvalidOperationException">Thrown when signing operation fails.</exception>
24+
public async Task<string> FunctionHandler(Input input, ILambdaContext context)
25+
{
26+
// Decode the Base64-encoded data back to bytes
27+
byte[] dataToSign = Convert.FromBase64String(input.DataToSign);
28+
29+
byte[]? result = SignData(dataToSign, input.DigestAlgorithm);
30+
31+
if (result != null)
32+
{
33+
return Convert.ToBase64String(result);
34+
}
35+
else
36+
{
37+
throw new InvalidOperationException("Signing operation failed");
38+
}
39+
}
40+
41+
/// <summary>
42+
/// Signs the provided data using RSA private key from a certificate.
43+
/// </summary>
44+
/// <param name="dataToSign">The byte array containing the data to be signed.</param>
45+
/// <param name="digestAlgorithm">The hash algorithm to use (Sha256, Sha384, or Sha512).</param>
46+
/// <returns>The signed data as a byte array.</returns>
47+
/// <exception cref="InvalidOperationException">Thrown when certificate does not contain an RSA private key.</exception>
48+
static byte[]? SignData(byte[] dataToSign, string? digestAlgorithm)
49+
{
50+
string certificateFilePassword = "johndoe";
51+
string certificateFilePath = "Resources/JohnDoe.pfx";
52+
53+
using (Stream stream = File.OpenRead(certificateFilePath))
54+
{
55+
byte[] certRawData = new byte[stream.Length];
56+
stream.ReadExactly(certRawData, 0, (int)stream.Length);
57+
58+
using (X509Certificate2 fullCert = new X509Certificate2(certRawData, certificateFilePassword))
59+
{
60+
using (RSA? rsa = fullCert.GetRSAPrivateKey())
61+
{
62+
if (rsa == null)
63+
{
64+
throw new InvalidOperationException("Certificate does not contain an RSA private key");
65+
}
66+
67+
// Map the digest algorithm string to HashAlgorithmName
68+
HashAlgorithmName algorithmName = HashAlgorithmName.SHA256;
69+
algorithmName = digestAlgorithm switch
70+
{
71+
"Sha384" => HashAlgorithmName.SHA384,
72+
"Sha512" => HashAlgorithmName.SHA512,
73+
_ => HashAlgorithmName.SHA256,
74+
};
75+
76+
byte[]? bytes = rsa.SignData(dataToSign, algorithmName, RSASignaturePadding.Pkcs1);
77+
return bytes;
78+
}
79+
}
80+
}
81+
}
82+
83+
/// <summary>
84+
/// Input model for the Lambda function containing data to sign and algorithm selection.
85+
/// </summary>
86+
public class Input
87+
{
88+
/// <summary>
89+
/// Gets or sets the Base64-encoded data to be signed.
90+
/// </summary>
91+
public string DataToSign { get; set; } = string.Empty;
92+
93+
/// <summary>
94+
/// Gets or sets the digest algorithm to use for signing (e.g., "Sha256", "Sha384", "Sha512").
95+
/// </summary>
96+
public string? DigestAlgorithm { get; set; }
97+
}
98+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"profiles": {
3+
"Mock Lambda Test Tool": {
4+
"commandName": "Executable",
5+
"commandLineArgs": "--port 5050",
6+
"workingDirectory": ".\\bin\\$(Configuration)\\net8.0",
7+
"executablePath": "%USERPROFILE%\\.dotnet\\tools\\dotnet-lambda-test-tool-8.0.exe"
8+
}
9+
}
10+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# ExternalSignAWSFunction
2+
3+
An AWS Lambda function that receives data to be signed, performs RSA signing with a private key certificate, and returns the signature bytes.
4+
5+
## Overview
6+
7+
This Lambda function serves as a secure signing service that keeps private keys in the AWS cloud environment. It is designed to work with PDF signing applications that use Telerik Document Processing or similar libraries for external signing scenarios.
8+
9+
## Features
10+
11+
- **Secure Key Storage**: Private keys remain in AWS Lambda, never exposed to clients
12+
- **RSA Signing**: Supports RSA signature generation with PKCS#1 padding
13+
- **Multiple Hash Algorithms**: Supports SHA256, SHA384, and SHA512
14+
- **Synchronous Invocation**: RequestResponse invocation for immediate results
15+
- **JSON Serialization**: Uses System.Text.Json for efficient serialization
16+
17+
## Prerequisites
18+
19+
- AWS Account with appropriate permissions
20+
- .NET 8.0 runtime
21+
- Valid X.509 certificate with private key (.pfx format)
22+
- AWS Lambda deployment tools (AWS CLI, SAM CLI, or Visual Studio AWS Toolkit)
23+
24+
## Dependencies
25+
26+
- [.NET 8.0 SDK](https://dotnet.microsoft.com/download/dotnet/8.0)
27+
- [Amazon.Lambda.Core](https://www.nuget.org/packages/Amazon.Lambda.Core/)
28+
29+
- ## Related Projects
30+
31+
- **SigningApp**: Client application that invokes this Lambda function for PDF signing
32+
33+
- - [AWS Lambda .NET Documentation](https://docs.aws.amazon.com/lambda/latest/dg/lambda-csharp.html)
34+
- [RSA Cryptography Documentation](https://docs.microsoft.com/dotnet/api/system.security.cryptography.rsa)
35+
36+
## License
37+
38+
This project is provided as a sample/demo. Please ensure you have appropriate licenses for:
39+
- Telerik Document Processing Library. Check the [Pricing and Licensing FAQ](https://www.telerik.com/faqs/pricing-and-licensing).
Binary file not shown.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"Information": [
3+
"This file provides default values for the deployment wizard inside Visual Studio and the AWS Lambda commands added to the .NET Core CLI.",
4+
"To learn more about the Lambda commands with the .NET Core CLI execute the following command at the command line in the project root directory.",
5+
"dotnet lambda help",
6+
"All the command line options for the Lambda command can be specified in this file."
7+
],
8+
"profile": "telerik-dpl",
9+
"region": "eu-north-1",
10+
"configuration": "Release",
11+
"package-type": "Image",
12+
"function-memory-size": 512,
13+
"function-timeout": 30,
14+
"image-command": "ExternalSignAWSFunctionApp::ExternalSignAWSFunctionApp.Function::FunctionHandler",
15+
"docker-host-build-output-dir": "./bin/Release/lambda-publish",
16+
"function-name": "ExternalSignPdfAWSFunction",
17+
"function-role": "",
18+
"function-architecture": "x86_64",
19+
"function-subnets": "",
20+
"function-security-groups": "",
21+
"tracing-mode": "PassThrough",
22+
"environment-variables": "",
23+
"dockerfile": "Dockerfile",
24+
"image-tag": "telerik/dpl:latest",
25+
"function-description": ""
26+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<Solution>
2+
<Project Path="ExternalSignAWSFunction/ExternalSignAWSFunction.csproj" />
3+
<Project Path="SigningApp/SigningApp.csproj" />
4+
</Solution>
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# External PDF Signing with AWS Lambda
2+
3+
A solution for digitally signing PDF documents using AWS Lambda with Telerik Document Processing, where the private key remains secure in AWS Lambda, separated from the document processing client application.
4+
5+
## Solution Overview
6+
7+
This solution demonstrates a secure architecture for PDF digital signatures where the private signing key remains in AWS Lambda, providing enhanced security by keeping sensitive keys in the cloud rather than on client machines.
8+
9+
### Architecture
10+
11+
```
12+
??????????????????? ????????????????????????
13+
? SigningApp ??????????? AWS Lambda ?
14+
? (Client) ? HTTPS ? (Signing Service) ?
15+
? ??????????? ?
16+
? - Telerik DPL ? ? - Private Key (.pfx) ?
17+
? - Public Key ? ? - RSA Signing ?
18+
??????????????????? ????????????????????????
19+
```
20+
21+
## Included Projects
22+
23+
- **ExternalSignAWSFunction** - AWS Lambda function that performs cryptographic signing
24+
- **SigningApp** - Client application that creates and signs PDF documents
25+
26+
## Dependencies
27+
28+
- [.NET 8.0 SDK](https://dotnet.microsoft.com/download/dotnet/8.0)
29+
- [AWS SDK for .NET](https://aws.amazon.com/sdk-for-net/)
30+
- [Telerik Document Processing](https://docs.telerik.com/devtools/document-processing/) - Check the [Pricing and Licensing FAQ](https://www.telerik.com/faqs/pricing-and-licensing)
31+
- [AWS Lambda Documentation](https://docs.aws.amazon.com/lambda/)
32+
- [Telerik Digital Signatures Documentation](https://docs.telerik.com/devtools/document-processing/libraries/radpdfprocessing/features/digital-signature)

0 commit comments

Comments
 (0)