Granting access by using an IAM role - AWS SDK for .NET

Granting access by using an IAM role

This tutorial shows you how to use the AWS SDK for .NET to enable IAM roles on Amazon EC2 instances.

Overview

All requests to AWS must be cryptographically signed by using credentials issued by AWS. Therefore, you need a strategy to manage credentials for applications that run on Amazon EC2 instances. You have to distribute, store, and rotate these credentials securely, but also keep them accessible to the applications.

With IAM roles, you can effectively manage these credentials. You create an IAM role and configure it with the permissions that an application requires, and then attach that role to an EC2 instance. Read more about the benefits of using IAM roles in the Amazon EC2 User Guide for Linux Instances or the Amazon EC2 User Guide for Windows Instances. Also see the information about IAM Roles in the IAM User Guide.

For an application that is built using the AWS SDK for .NET, when the application constructs a client object for an AWS service, the object searches for credentials from several potential sources. The order in which it searches is shown in Credential and profile resolution.

If the client object doesn't find credentials from any other source, it retrieves temporary credentials that have the same permissions as those that have been configured into the IAM role and are in the metadata of the EC2 instance. These credentials are used to make calls to AWS from the client object.

About this tutorial

As you follow this tutorial, you use the AWS SDK for .NET (and other tools) to launch an Amazon EC2 instance with an IAM role attached, and then see an application on the instance using the permissions of the IAM role.

Create a sample Amazon S3 application

This sample application retrieves an object from Amazon S3. To run the application, you need the following:

  • An Amazon S3 bucket that contains a text file.

  • AWS credentials on your development machine that allow you to access to the bucket.

For information about creating an Amazon S3 bucket and uploading an object, see the Amazon Simple Storage Service User Guide. For information about AWS credentials, see Configure SDK authentication with AWS.

Create a .NET Core project with the following code. Then test the application on your development machine.

Note

On your development machine, the .NET Core Runtime is installed, which enables you to run the application without publishing it. When you create an EC2 instance later in this tutorial, you can choose to install the .NET Core Runtime on the instance. This gives you a similar experience and a smaller file transfer.

However, you can also choose not to install the .NET Core Runtime on the instance. If you choose this course of action, you must publish the application so that all dependencies are included when you transfer it to the instance.

NuGet packages:

Programming elements:

using System; using System.Collections.Generic; using System.IO; using System.Threading.Tasks; using Amazon.S3; using Amazon.S3.Model; namespace S3GetTextItem { // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = // Class to retrieve a text file from an S3 bucket and write it to a local file class Program { static async Task Main(string[] args) { // Parse the command line and show help if necessary var parsedArgs = CommandLine.Parse(args); if(parsedArgs.Count == 0) { PrintHelp(); return; } // Get the application arguments from the parsed list string bucket = CommandLine.GetArgument(parsedArgs, null, "-b", "--bucket-name"); string item = CommandLine.GetArgument(parsedArgs, null, "-t", "--text-object"); string outFile = CommandLine.GetArgument(parsedArgs, null, "-o", "--output-filename"); if( string.IsNullOrEmpty(bucket) || string.IsNullOrEmpty(item) || string.IsNullOrEmpty(outFile)) CommandLine.ErrorExit( "\nOne or more of the required arguments is missing or incorrect." + "\nRun the command with no arguments to see help."); // Create the S3 client object and get the file object from the bucket. var response = await GetObject(new AmazonS3Client(), bucket, item); // Write the contents of the file object to the given output file. var reader = new StreamReader(response.ResponseStream); string contents = reader.ReadToEnd(); using (var s = new FileStream(outFile, FileMode.Create)) using (var writer = new StreamWriter(s)) writer.WriteLine(contents); } // // Method to get an object from an S3 bucket. private static async Task<GetObjectResponse> GetObject( IAmazonS3 s3Client, string bucket, string item) { Console.WriteLine($"Retrieving {item} from bucket {bucket}."); return await s3Client.GetObjectAsync(bucket, item); } // // Command-line help private static void PrintHelp() { Console.WriteLine( "\nUsage: S3GetTextItem -b <bucket-name> -t <text-object> -o <output-filename>" + "\n -b, --bucket-name: The name of the S3 bucket." + "\n -t, --text-object: The name of the text object in the bucket." + "\n -o, --output-filename: The name of the file to write the text to."); } } // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = // Class that represents a command line on the console or terminal. // (This is the same for all examples. When you have seen it once, you can ignore it.) static class CommandLine { // // Method to parse a command line of the form: "--key value" or "-k value". // // Parameters: // - args: The command-line arguments passed into the application by the system. // // Returns: // A Dictionary with string Keys and Values. // // If a key is found without a matching value, Dictionary.Value is set to the key // (including the dashes). // If a value is found without a matching key, Dictionary.Key is set to "--NoKeyN", // where "N" represents sequential numbers. public static Dictionary<string,string> Parse(string[] args) { var parsedArgs = new Dictionary<string,string>(); int i = 0, n = 0; while(i < args.Length) { // If the first argument in this iteration starts with a dash it's an option. if(args[i].StartsWith("-")) { var key = args[i++]; var value = key; // Check to see if there's a value that goes with this option? if((i < args.Length) && (!args[i].StartsWith("-"))) value = args[i++]; parsedArgs.Add(key, value); } // If the first argument in this iteration doesn't start with a dash, it's a value else { parsedArgs.Add("--NoKey" + n.ToString(), args[i++]); n++; } } return parsedArgs; } // // Method to get an argument from the parsed command-line arguments // // Parameters: // - parsedArgs: The Dictionary object returned from the Parse() method (shown above). // - defaultValue: The default string to return if the specified key isn't in parsedArgs. // - keys: An array of keys to look for in parsedArgs. public static string GetArgument( Dictionary<string,string> parsedArgs, string defaultReturn, params string[] keys) { string retval = null; foreach(var key in keys) if(parsedArgs.TryGetValue(key, out retval)) break; return retval ?? defaultReturn; } // // Method to exit the application with an error. public static void ErrorExit(string msg, int code=1) { Console.WriteLine("\nError"); Console.WriteLine(msg); Environment.Exit(code); } } }

If you want, you can temporarily remove the credentials you use on your development machine to see how the application responds. (But be sure to restore the credentials when you're finished.)

Create an IAM role

Create an IAM role that has the appropriate permissions to access Amazon S3.

  1. Open the IAM console.

  2. In the navigation pane, choose Roles, and then choose Create Role.

  3. Select AWS service, find and choose EC2, and choose Next: Permissions.

  4. Under Attach permissions policies, find and select AmazonS3ReadOnlyAccess. Review the policy if you want to, and then choose Next: Tags.

  5. Add tags if you want and then choose Next: Review.

  6. Type a name and description for the role, and then choose Create role. Remember this name because you'll need it when you launch your EC2 instance.

Launch an EC2 instance and attach the IAM role

Launch an EC2 instance with the IAM role you created previously. You can do so in the following ways.

To launch an EC2 instance that has an IAM role attached, an IAM user's configuration must include certain permissions. For more information about the required permissions, see the Amazon EC2 User Guide for Linux Instances or the Amazon EC2 User Guide for Windows Instances.

Connect to the EC2 instance

Connect to the EC2 instance so that you can transfer the sample application to it and then run the application. You'll need the file that contains the private portion of the key pair you used to launch the instance; that is, the PEM file.

You can do this by following the connect procedure in the Amazon EC2 User Guide for Linux Instances or the Amazon EC2 User Guide for Windows Instances. When you connect, do so in such a way that you can transfer files from your development machine to your instance.

If you're using Visual Studio on Windows, you can also connect to the instance by using the Toolkit for Visual Studio. For more information, see Connecting to an Amazon EC2 Instance in the AWS Toolkit for Visual Studio User Guide.

Run the sample application on the EC2 instance

  1. Copy the application files from your local drive to your instance.

    Which files you transfer depends on how you built the application and whether your instance has the .NET Core Runtime installed. For information about how to transfer files to your instance see the Amazon EC2 User Guide for Linux Instances or the Amazon EC2 User Guide for Windows Instances.

  2. Start the application and verify that it runs with the same results as on your development machine.

  3. Verify that the application uses the credentials provided by the IAM role.

    1. Open the Amazon EC2 console.

    2. Select the instance and detach the IAM role through Actions, Instance Settings, Attach/Replace IAM Role.

    3. Run the application again and see that it returns an authorization error.

Clean up

When you are finished with this tutorial, and if you no longer want the EC2 instance you created, be sure to terminate the instance to avoid unwanted cost. You can do so in the Amazon EC2 console or programmatically, as described in Terminating an Amazon EC2 instance. If you want to, you can also delete other resources that you created for this tutorial. These might include an IAM role, an EC2 keypair and PEM file, a security group, etc.