AWS .NET - 1.0
Extension ID
com.castsoftware.awsdotnet
What’s new?
See AWS .NET 1.0 - Release Notes.
In what situation should you install this extension?
The AWS.NET extension is responsible of creating objects describing Amazon Web Service (AWS) Lambda functions but only in the context of dotnet technology. (Similarly, the NodeJS extension is responsible of AWS lambda Functions created for the nodejs runtime). To run fully, this extension requires a Universal Analysis Unit with the HTML5 language switched on. This allows analyzing the .json or .yml configuration files (which are used by deployment frameworks to build aws applications). The supported deployment frameworks are Serverless Framework, CloudFormation, and Serverless Application Model (SAM).
The complementary analysis responsible for creating Java Call to AWS Lambda Function objects is based on the analysis of java files and it will be launched without any further requirement upon installation of the com.castsoftware.awsjava plugin.
Only Serverless Framework, CloudFormation, and Serverless Application Model (SAM) deployment frameworks are supported.
Objects
Icon | Description | Entry Point (Transaction Configuration) | End Point (Transaction Configuration) | Data Entity (Transaction Configuration) |
---|---|---|---|---|
DotNet AWS SQS Receiver |
(only when not called by other objects) |
- | - | |
DotNet AWS SNS Subscriber |
(only when not called by other objects) |
- | - | |
DotNet AWS SQS Publisher | - |
(only when it is not calling any other object) |
- | |
DotNet AWS SNS Publisher | - |
(only when it is not calling any other object) |
- | |
DotNet AWS unknown SQS Receiver | - | - | ||
DotNet AWS unknown SNS Subscriber | - | - | ||
DotNet AWS unknown SQS Publisher | - | - | ||
DotNet AWS unknown SNS Publisher | - | - | ||
Dotnet AWS Call to AWS Lambda Function | - |
(only when it is not calling any other object) |
- | |
DotNet AWS Call to unknown Lambda | - |
|
- | |
Dotnet AWS Email | - |
|
- | |
Dotnet AWS SMS | - |
|
- | |
Dotnet AWS Post Service | - |
(only when it is not calling any other object) |
- | |
Dotnet AWS S3 Bucket | - | - | ||
Dotnet AWS unknown S3 Bucket | - | - |
Support for Lambda functions
Lambda services (or functions) allow executing some source code on the cloud. The execution can be set to be triggered by some AWS events. Lambda functions can be deployed using several deployment frameworks. The supported deployment frameworks are listed on AWS Lambda. When a lambda function is created and its runtime is dotnet, the current extension is responsible for linking the lambda objects and their triggers with the java handler functions.
Example
Let us consider a source code defining a lambda function having a dotnet runtime (for instance dotnetcore3.0) and the handler function is given by the handler function fullname. If the lambda function is deployed using a supported deployment framework (such as CloudFormation), the analysis will create a lambda function. If the current extension finds a C# method matching the handler fullname a link to that method will be added from the lambda function.
Some applications are using a monolithic pattern: only one handler function is used for many (if not all) API Gateways. That handler function then dispatches the call to sub-handler functions using switches based on the URLs. Ideally, in the modelization, each API Gateway should be linked to its dedicated sub-handler function. However, in our modelization, all API Gateways will be linked to the root handler function.
Support for SDK
The extension supports only the API for the V3 SDK as the V2 SDK is deprecated and no longer supported.
Support for SNS
The following APIs are supported:
- Amazon.SimpleNotificationService.AmazonSimpleNotificationServiceClient.Publish
- Amazon.SimpleNotificationService.AmazonSimpleNotificationServiceClient.PublishAsync
- Amazon.SimpleNotificationService.AmazonSimpleNotificationServiceClient.Subscribe
For the Publish method, a AWS Dotnet SNS Publisher object is created. Its name is that of the topic. For the Subscribe methods, a AWS Dotnet SNS Subscriber object is created. Its name is that of the topic. Then for each supported protocol, an object is created with a callLink from the subscriber to that object. The supported protocols are the following:
protocol | object created | name of the object |
Dotnet AWS Email | an Email (the email addresses are not evaluated) | |
sms | Dotnet AWS SMS | an SMS (the SMS numbers are not evaluated) |
http/https | Dotnet AWS Post Service | the url (evaluated from the endpoint) |
sqs | Dotnet AWS Simple Queue Service Publisher | the name of the queue (evaluated from the endpoint) |
lambda | Dotnet AWS Call to Lambda Function | the name of the lambda function (evaluated from the endpoint) |
The com.castsoftware.wbslinker will create a callLink between the SNS Publishers and SNS Subscribers which have the same name.
Example
When analyzing the following source code:
void sendSNSMessage(string[] args)
{
AmazonSimpleNotificationServiceClient snsClient = new AmazonSimpleNotificationServiceClient(Amazon.RegionEndpoint.USWest2);
var topicRequest = new CreateTopicRequest();
topicRequest.Name = "Sport";
var topicResponse = snsClient.CreateTopic(topicRequest);
var topicAttrRequest = new SetTopicAttributesRequest();
topicAttrRequest.TopicArn = topicResponse.TopicArn;
topicAttrRequest.AttributeName = "DisplayName";
topicAttrRequest.AttributeValue = "Coding Test Results";
snsClient.SetTopicAttributes(topicAttrRequest);
Dictionary<string, MessageAttributeValue> messageAttributes = new Dictionary<string, MessageAttributeValue>();
MessageAttributeValue v1 = new MessageAttributeValue();
v1.DataType = "String";
v1.StringValue = "senderidx";
messageAttributes.Add("AWS.SNS.SMS.SenderID", v1);
MessageAttributeValue v2 = new MessageAttributeValue();
v2.DataType = "String";
v2.StringValue = "0.50";
messageAttributes.Add("AWS.SNS.SMS.MaxPrice", v2);
MessageAttributeValue v3 = new MessageAttributeValue();
v3.DataType = "String";
// Options: Promotional, Transactional
v3.StringValue = "Promotional";
messageAttributes.Add("AWS.SNS.SMS.SMSType", v3);
SendLambdaAsync(snsClient, "Hello from AWS SNS!", "+1 XXX YYYYYY", messageAttributes).Wait();
}
static async Task SendLambdaAsync(AmazonSimpleNotificationServiceClient snsClient, string message, string phoneNumber,
Dictionary<string, MessageAttributeValue> messageAttributes)
{
PublishRequest publishRequest = new PublishRequest();
publishRequest.Message = message;
publishRequest.MessageAttributes = messageAttributes;
try
{
var response = await snsClient.PublishAsync(publishRequest);
Console.WriteLine(response.MessageId);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
void SQSLambda(string[] args)
{
AmazonSimpleNotificationServiceClient snsClient = new AmazonSimpleNotificationServiceClient(Amazon.RegionEndpoint.USWest2);
var topicRequest = new CreateTopicRequest
{
Name = "Sport"
};
var topicResponse = snsClient.CreateTopic(topicRequest);
var topicAttrRequest = new SetTopicAttributesRequest
{
TopicArn = topicResponse.TopicArn,
AttributeName = "DisplayName",
AttributeValue = "Coding Test Results"
};
snsClient.SetTopicAttributes(topicAttrRequest);
snsClient.Subscribe(new SubscribeRequest
{
Endpoint = "arn:aws:lambda:us-east-1:123456789012:function:sns-same-account",
Protocol = "lambda",
TopicArn = topicResponse.TopicArn
});
}
Alternative example with SQS protocol:
Click to enlarge
Support for SQS
The following APIs are supported:
- Amazon.SQS.AmazonSQSClient.SendMessage
- Amazon.SQS.AmazonSQSClient.SendMessageAsync
- Amazon.SQS.AmazonSQSClient.SendMessageBatch
- Amazon.SQS.AmazonSQSClient.SendMessageBatchAsync
- Amazon.SQS.AmazonSQSClient.ReceiveMessage
- Amazon.SQS.AmazonSQSClient.ReceiveMessageAsync
For the SendMessage methods, a AWS Dotnet SQS Publisher object is created. Its name is that of the topic. For the ReceiveMessage methods, a AWS Dotnet SQS Receiver object is created. Its name is that of the topic.
Example
When analyzing the following source code:
public static void MainSQS(string[] args)
{
//the url for our queue
var queueUrl = "https://sqs.eu-west-1.amazonaws.com/[USERID]/[QUEUENAME]";
Console.WriteLine("Queue Test Starting!");
Console.WriteLine("Creating Client and request");
//Create some Credentials with our IAM user
var awsCreds = new BasicAWSCredentials("[ACCESSKEY]", "[SECRETKEY]");
//Create a client to talk to SQS
var amazonSQSClient = new AmazonSQSClient(awsCreds,Amazon.RegionEndpoint.EUWest1);
//Create the request to send
var sendRequest = new SendMessageRequest();
sendRequest.QueueUrl = "https://sqs.eu-west-1.amazonaws.com/[USERID]/[QUEUENAME]";//queueUrl;
sendRequest.MessageBody = "{ 'message' : 'hello world' }";
//Send the message to the queue and wait for the result
Console.WriteLine("Sending Message");
var sendMessageResponse = amazonSQSClient.SendMessageAsync(sendRequest).Result;
Console.WriteLine("Receiving Message");
//Create a receive requesdt to see if there are any messages on the queue
var receiveMessageRequest = new ReceiveMessageRequest();
receiveMessageRequest.QueueUrl = "https://sqs.eu-west-1.amazonaws.com/[USERID]/[QUEUENAME]"//queueUrl;
//Send the receive request and wait for the response
var response = amazonSQSClient.ReceiveMessageAsync(receiveMessageRequest).Result;
//If we have any messages available
if(response.Messages.Any())
{
foreach(var message in response.Messages)
{
//Spit it out
Console.WriteLine(message.Body);
//Remove it from the queue as we don't want to see it again
var deleteMessageRequest = new DeleteMessageRequest();
deleteMessageRequest.QueueUrl = queueUrl;
deleteMessageRequest.ReceiptHandle = message.ReceiptHandle;
var result = amazonSQSClient.DeleteMessageAsync(deleteMessageRequest).Result;
}
}
}
public static void MainSQS(string[] args)
{
//the url for our queue
var queueUrl = "https://sqs.eu-west-1.amazonaws.com/[USERID]/[QUEUENAME]";
Console.WriteLine("Queue Test Starting!");
Console.WriteLine("Creating Client and request");
//Create some Credentials with our IAM user
var awsCreds = new BasicAWSCredentials("[ACCESSKEY]", "[SECRETKEY]");
//Create a client to talk to SQS
var amazonSQSClient = new AmazonSQSClient(awsCreds,Amazon.RegionEndpoint.EUWest1);
//Create the request to send
var sendRequest = new SendMessageRequest();
sendRequest.QueueUrl = "https://sqs.eu-west-1.amazonaws.com/[USERID]/[QUEUENAME]";//queueUrl;
sendRequest.MessageBody = "{ 'message' : 'hello world' }";
//Send the message to the queue and wait for the result
Console.WriteLine("Sending Message");
var sendMessageResponse = amazonSQSClient.SendMessageAsync(sendRequest).Result;
Console.WriteLine("Receiving Message");
//Create a receive requesdt to see if there are any messages on the queue
var receiveMessageRequest = new ReceiveMessageRequest();
receiveMessageRequest.QueueUrl = "https://sqs.eu-west-1.amazonaws.com/[USERID]/[QUEUENAME]"//queueUrl;
//Send the receive request and wait for the response
var response = amazonSQSClient.ReceiveMessageAsync(receiveMessageRequest).Result;
//If we have any messages available
if(response.Messages.Any())
{
foreach(var message in response.Messages)
{
//Spit it out
Console.WriteLine(message.Body);
//Remove it from the queue as we don't want to see it again
var deleteMessageRequest = new DeleteMessageRequest();
deleteMessageRequest.QueueUrl = queueUrl;
deleteMessageRequest.ReceiptHandle = message.ReceiptHandle;
var result = amazonSQSClient.DeleteMessageAsync(deleteMessageRequest).Result;
}
}
}
Support for Lambda Invoke
Lambda invoke with AWS SDK:
public static void Main(string playerName, Action<string> callback)
{
var client = new AmazonLambdaClient();
var sqsEvent = new SQSEvent
{
Records = new List<SQSEvent.SQSMessage>
{
new SQSEvent.SQSMessage
{
Body = "Hello Lambda!"
}
}
};
var request = new InvokeRequest
{
FunctionName = "1-direct-invocation",
// force sync lambda invocation
InvocationType = InvocationType.RequestResponse,
LogType = LogType.Tail,
Payload = JsonSerializer.Serialize(sqsEvent)
};
var result = await client.InvokeAsync(request);
}
Support for AWS S3
S3 Bucket with AWS SDK
static string bucketName = "S3WestAsieRegion";
static string key = $"key-{Guid.NewGuid().ToString("n").Substring(0, 8)}";
static void Main(string[] args)
{
using (var s3 = new AmazonS3Client(RegionEndpoint.USWest2))
{
CreateBucket(s3);
WriteObject(s3);
...
}
}
static void CreateBucket(IAmazonS3 s3)
{
Task<PutBucketResponse> res = s3.PutBucketAsync(new PutBucketRequest().WithBucketName(bucketName));
Task.WaitAll(res);
if (res.IsCompletedSuccessfully)
{
Console.WriteLine("New S3 bucket created: {0}", bucketName);
}
}
static void WriteObject(IAmazonS3 s3)
{
// The api call used in this method equates to S3's Put api and is
// suitable for smaller files. To upload larger files and entire
// folder hierarchies, with automatic usage of S3's multi-part apis for
// files over 5MB in size, consider using the TransferUtility class
// in the Amazon.S3.Transfer namespace.
// See https://docs.aws.amazon.com/AmazonS3/latest/dev/HLuploadFileDotNet.html.
var ms = new MemoryStream(Encoding.UTF8.GetBytes("Test S3 data"));
var req = new PutObjectRequest
{
BucketName = bucketName,
Key = key,
InputStream = ms
};
Task<PutObjectResponse> res = s3.PutObjectAsync(req);
Task.WaitAll(res);
if (res.IsCompletedSuccessfully)
{
Console.WriteLine("Created object '{0}' in bucket '{1}'", key, bucketName);
}
}
Linking
The extension com.castsoftware.wbslinker is responsible for matching these objects during application-level analysis with cross-technology:
- SNS publisher and SNS subscriber
- SQS publisher and SQS subscriber
- AWS Lambda Call and AWS Lambda object
- AWS Http Post service and operation Post
Data sensitivity
This extension is capable of setting a property on AWS S3 Bucket objects for the following:
- custom sensitivity
- GDPR
- PCI-DSS
See Data Sensitivity for more information.
Known limitations
- Monolithic pattern for lambda functions is not supported properly
- The use of access points is not supported.