Page tree
Skip to end of metadata
Go to start of metadata

Extension ID

com.castsoftware.awsdotnet

What's new?

See AWS .NET 1.0 - Release Notes for more information.

In what situation should you install this extension?

The AWSDotNet 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

IconDescriptionTransaction Configuration definition
Entry PointEnd PointData Entity

DotNet AWS SQS Receiver

(tick) 

(only when not called by other objects)



DotNet AWS SNS Subscriber

(tick)

(only when not called by other objects)



DotNet AWS SQS Publisher

(tick) 

(only when it is not calling any other object)


 DotNet AWS SNS Publisher

(tick) 

(only when it is not calling any other object)


DotNet AWS unknown SQS Receiver(tick)

DotNet AWS unknown SNS Subscriber(tick)

DotNet AWS unknown SQS Publisher
(tick)

DotNet AWS unknown SNS Publisher 

(tick)


Dotnet AWS Call to AWS Lambda Function


(tick) 

(only when it is not calling any other object)


DotNet AWS Call to unknown Lambda

(tick) 


Dotnet AWS Email

(tick) 


Dotnet AWS SMS

(tick) 


Dotnet AWS Post Service

(tick) 

(only when it is not calling any other object)


Dotnet AWS S3 Bucket

(tick)

Dotnet AWS unknown S3 Bucket

(tick)

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 this page.

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 that has two triggers: an SQS queue and an API Gateway. The lambda function has 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, an SQS receiver, and an API Gateway objects. Each of these objects has a runtime property (dotnetcore3.0) and a handler property with the function fullname. 

If the current extension finds a C# method matching the handler fullname a link to that method will be added from the lambda function, the SQS queue and the API Gateway objects.

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:

protocolobject createdname of the object
emailDotnet  AWS Emailan Email   (the email addresses are not evaluated)
smsDotnet AWS SMSan SMS   (the SMS numbers are not evaluated)
http/httpsDotnet  AWS Post Servicethe url (evaluated from the endpoint)
sqsDotnet AWS Simple Queue Service Publisherthe name of the queue (evaluated from the endpoint)
lambdaDotnet AWS Call to Lambda Functionthe 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:

Publisher

        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
			});
        }

Result in CAST Enlighten:

Click to enlarge

Other 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:

Publisher

        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;
                }
            }

        }

Receiver

        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;
                }
            }

        }

Result in CAST Enlighten:

Click to enlarge

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);
	    }

Result in CAST Enlighten:

Click to enlarge

Support 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);
            }
        }

Result in CAST Enlighten:

Click to enlarge

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

Known limitations

  • Monolithic pattern for lambda functions is not supported properly
  • The use of access points is not supported.
  • No labels