Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to specify AWS credentials in C# .NET core console program

I am trying to test a .NET core console program to publish a message to SNS. As I had issues trying to get it to work in Lambda, I want to try it in a non-Lambda environment. In Lambda, security is covered by the role, but in a console program, I presume that I have to specify my access key and secret somehow.

I've read this page: http://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/net-dg-config-creds.html#net-dg-config-creds-sdk-store, but still totally confused.

I'm running on my local development computer, not an EC2 instance. No intent to go to production with this, just trying to test some code.

I'm on Visual Studio 2015, .NET Core 1.0. I've used Nuget to get the following: "AWSSDK.Extensions.NETCore.Setup": "3.3.3", "AWSSDK.SimpleNotificationService": "3.3.0.23",

Based on the answer to How to set credentials on AWS SDK on NET Core? I created the /user/.aws/credentials file (assuming credentials was the file name and not the directory name).

But that question/answer doesn't address how to actually use this file. The code I'm running is below.

    public static void Main(string[] args)     {         Console.WriteLine("Started");         //var awsCredentials = new Amazon.Runtime.AWSCredentials()         var client = new Amazon.SimpleNotificationService.AmazonSimpleNotificationServiceClient(Amazon.RegionEndpoint.EUWest2);         //var client = new Amazon.SimpleNotificationService.AmazonSimpleNotificationServiceClient(awsCredentials, Amazon.RegionEndpoint.EUWest2);         //Amazon.SimpleNotificationService.Model.PublishResponse publishResp = null;         SendMessage(client).Wait();         Console.WriteLine("Completed call to SendMessage: Press enter to end:");         Console.ReadLine();      } 

The error I'm getting on the new client is:

An unhandled exception of type 'Amazon.Runtime.AmazonServiceException' occurred in AWSSDK.Core.dll  Additional information: Unable to find credentials 

I see there is a way to pass an AWSCredentials object to that constructor, but I don't understand how to build it. Amazon.Runtime.AWSCredentials is an abstract class, so I can't use it in a "new" statement.

like image 878
NealWalters Avatar asked Nov 05 '17 18:11

NealWalters


People also ask

Where are AWS credentials stored locally?

The AWS CLI stores sensitive credential information that you specify with aws configure in a local file named credentials , in a folder named . aws in your home directory. The less sensitive configuration options that you specify with aws configure are stored in a local file named config , also stored in the .

What format is AWS credentials file?

We recommend downloading these files from the AWS Management Console by following the instructions for Managing access keys in the IAM User Guide. Both the shared config and credentials files are plaintext files that contain only ASCII characters (UTF-8 encoded).


2 Answers

Based on Dan Pantry's answer, here is a simple short answer with code highlighted (note the region enum in the second line):

var awsCredentials = new Amazon.Runtime.BasicAWSCredentials("myaccesskey", "mysecretkey");  var client = new Amazon.SimpleNotificationService.AmazonSimpleNotificationSer‌​viceClient(                               awsCreden‌​tials, Amazon.RegionEndpoint.EUWest2); 

Use a role if possible, but above works when needed. Then the question is where to store the access key/secret key; could be environment variable, config file, prompt the user, or any of the usual suspects.

AWS-CLI and Python use credentials from here: c:\Users\username\.aws\credentials, so the C# could just read that file so as not to put the codes in the C# program itself. But then each user/developer that runs the program would need to set their credentials there.

There is also now a concept of running Lambda on your local machine, but I haven't tried it yet: https://dzone.com/articles/run-aws-lambda-functions-locally-on-windows-machin#:~:text=Step%201%3A%20Download%20SAM%20local,version%20with%20the%20command%20below.&text=Step%203%3A%20Write%20your%20lambda,yaml%20on%20the%20root%20level. So the point is that if you are going to do Lambda, but you need to test locally first, this would probably be worth trying.

like image 141
NealWalters Avatar answered Sep 21 '22 00:09

NealWalters


You'll want to construct one of its child classes instead of the abstract one. You can take a look at the class hierarchy here.

For posterity, the options are:

  • AnonymousAWSCredentials - Authenticates as an anonymous user.
  • BasicAWSCredentials - You provide your credentials to the class constructor directly.
  • EnvironmentAWSCredentials - Credentials are pulled from the environment variables of the running executable.
  • InstanceProfileAWSCredentials - Pulls credentials from the Instance Profile of the EC2 instance running the executable. This, obviously, only works on EC2.
  • SessionAWSCredentials - Similar to BasicAWSCredentials, except utilises an AWS Session using a temporary session token from AWS STS.
  • RefreshingSessionAWSCredentials - Similar to SessionAWSCredentials, but refreshes when the STS token expires.

Note that the default strategy in the absence of a credentials object involves checking the Environment Variables and then the instance profile.

If you want to have the program pull credentials from ~/.aws/credentials, you'll need to do some legwork. There used to be a StoredProfileAWSCredentials class, but that appears to have been removed - you can find more information by looking at this github issue. This is only useful, really, in development as you won't be using ~/.aws/credentials in production but probably instance profiles - I'd suggest instead using the default strategy and using Environment AWS credentials in test or development environments.

I take this approach at work since we use a command line tool to grab us limited time tokens from AWS STS and plunk them into the current shell for use for the next hour.

EDIT: It appears you're using AWS Lambda. These have federated access to AWS resources based on the roles assigned to them, so this should work using the default credential strategy in the aws-sdk library which uses instance profiles. So this is only really necessary for development/testing, in which case I would again recommend just using environment variables.

like image 30
3 revs, 2 users 89% Avatar answered Sep 20 '22 00:09

3 revs, 2 users 89%