You can access AWS services using your corporate credentials as defined in your existing Active Directory Federation Services (ADFS) setup. You can also integrate AWS with ADFS to implement single sign-on functionality. When using ADFS with AWS, ADFS acts as the identity provider and AWS acts as a relying party. This recipe includes commands and instructions to create a proxy server to get the temporary credentials from AWS Security Token Service (STS) and a client application that accesses an S3 bucket (using the temporary credentials) from a C# application.
Create a simple Windows Communication Foundation (WCF) application and add a WCF service class. WCF is a framework for building service-oriented applications. Using WCF, you can send data as asynchronous messages from one service endpoint to another. A service endpoint can be a part of continuously available service hosted by IIS, or it can be a service hosted in an application. In the class, create a Get method that calls STS service for the temporary credentials.
TemporaryCredentials IProxyService.GetToken() { //Get username from client request. string userName = HttpContext.Current.Request.LogonUserIdentity.Name; TemporaryCredentials objTemporaryCredentials = new TemporaryCredentials(); //Get the app settings from web.config file. NameValueCollection appConfig = ConfigurationManager.AppSettings; string accessKeyId = appConfig["accessKeyId"]; string secretAccessKey = appConfig["secretAccessKey"]; string bucketName = appConfig["bucketName"]; // Create a client. AmazonSecurityTokenServiceConfig config = new AmazonSecurityTokenServiceConfig(); AmazonSecurityTokenServiceClient client = new AmazonSecurityTokenServiceClient( accessKeyId, secretAccessKey, config); //Split the user name. string[] usernameParts01 = userName.Split(''); // Build the aws username. string awsUsernameDomain = usernameParts01[1] + "@" + usernameParts01[0]; // Split username@domain to retrieve the username only. string[] usernameParts02 = awsUsernameDomain.Split('@'); //Get username only. string awsUsername = usernameParts02[0]; string policy = appConfig["policy_" + awsUsername]; // Replace the [*] values with real values at runtime. policy = policy.Replace("[BUCKET-NAME]", bucketName); policy = policy.Replace("[USER-NAME]", awsUsername.ToLowerInvariant()); policy = policy.Replace("'", """); //Request to get temporary credentials. GetFederationTokenRequest request = new GetFederationTokenRequest { DurationSeconds = 3600 * 8, Name = awsUsername, Policy = policy }; //Get temporary credentials. GetFederationTokenResponse objGetFederationTokenResponse = client.GetFederationToken(request); //Get federation token result. GetFederationTokenResult objGetFederationTokenResult = objGetFederationTokenResponse.GetFederationTokenResult; //Get credentials. Credentials objCredentials = objGetFederationTokenResult.Credentials; //Set user name. objTemporaryCredentials.User = userName; //Set access key id. objTemporaryCredentials.AccessKeyId = objCredentials.AccessKeyId; //Set secret access key. objTemporaryCredentials.SecretAccessKey = objCredentials.SecretAccessKey; //Set expiration. objTemporaryCredentials.Expiration = objCredentials.Expiration; //Set token. objTemporaryCredentials.Token = objCredentials.SessionToken; //Return result. return objTemporaryCredentials; }
policy_username
key.Using policy file specified, the user can list objects in the specified bucket and get objects from the folder with his name:
{ 'Statement': [ { 'Sid': 'PersonalBucketAccess', 'Action': [ 's3:GetObject' ], 'Effect': 'Allow', 'Resource': 'arn:aws:s3:::[BUCKET-NAME]/[USER- NAME]/*' }, { 'Sid': 'GeneralBucketList', 'Action': [ 's3:ListBucket' ], 'Effect': 'Allow', 'Resource': 'arn:aws:s3:::[BUCKET-NAME]' } ] }
web.config
file. The configuration sets the security mode to TransportCredentialOnly
.<bindings> <webHttpBinding> <binding name="default"> <security mode="TransportCredentialOnly"> <transport clientCredentialType="Windows" proxyCredentialType="Windows" /> </security> </binding> </webHttpBinding> </bindings>
Create a C# console application that accomplishes the following tasks:
If you try to access the folder belonging to a user other than the logged-in user, you will get an access denied message.
//Web request to call proxy service. HttpWebRequest request = (HttpWebRequest)WebRequest.Create(" http://ProxyServiceURL/ProxyService.svc/GetToken "); request.UseDefaultCredentials = true; request.Credentials = System.Net.CredentialCache.DefaultCredentials; //Get the response. HttpWebResponse response = response = (HttpWebResponse)request.GetResponse(); //Check for status code. if (response.StatusCode == HttpStatusCode.OK) { //Get response stream. using (StreamReader reader = new StreamReader(response.GetResponseStream())) { //Read response. string json = reader.ReadToEnd(); //Initialize DataContractJsonSerializer. DataContractJsonSerializer serializer = new DataContractJsonSerializer (typeof(TemporaryCredentials)); //Get memory stream. MemoryStream ms = new MemoryStream (Encoding.Default.GetBytes(json)); //Get deserialized object. TemporaryCredentials objTemporaryCredentials = (TemporaryCredentials) serializer.ReadObject(ms); //Bucket name. string bucketName = "clientdocs01"; //File name. string fileName = "administrator/Note.txt"; //Set AWS credentials and token. SessionAWSCredentials objSessionAWSCredentials = new SessionAWSCredentials( objTemporaryCredentials.AccessKeyId, objTemporaryCredentials.SecretAccessKey, objTemporaryCredentials.Token); //Create S3 client object to access S3 service. AmazonS3Client objAmazonS3Client = new AmazonS3Client(objSessionAWSCredentials, Amazon.RegionEndpoint.APSoutheast1); //Prepare list object request. ListObjectsRequest objListObjectsRequest = new ListObjectsRequest(); //Set bucket name. objListObjectsRequest.BucketName = bucketName; //Get response from AWS S3. ListObjectsResponse objListObjectsResponse = objAmazonS3Client.ListObjects (objListObjectsRequest); //Iterate over S3 objects. for (int i = 0; i < objListObjectsResponse.S3Objects.Count; i++) { //Display object name. Console.WriteLine(" " + objListObjectsResponse. S3Objects[i].Key); } //Prepare get object request. GetObjectRequest objGetObjectRequest = new GetObjectRequest(); //Set bucket name. objGetObjectRequest.BucketName = bucketName; //Set file name. objGetObjectRequest.Key = fileName; //Get object data. GetObjectResponse objGetObjectResponse = objAmazonS3Client.GetObject (objGetObjectRequest); //Get response stream. using (StreamReader objStreamReader = new StreamReader (objGetObjectResponse.ResponseStream)) { //Read response. Console.WriteLine("Contents :" + objStreamReader.ReadToEnd()); } } }
AD FS integration is an important organization because their users don't need to use a different set of credentials for AWS access. The proxy application used to get temporary credentials from AWS
Security Token Service (STS) should be a domain-joined machine. The proxy server stores the mapping between the user and the policy. To retrieve temporary credentials, the proxy server needs AccessKeyId
and SecretAccessKey
. We create an IAM user, assign the permissions, and create access keys for the user.
Before creating the sample application, download the .Net SDK using NuGet packager. In Visual Studio's NuGet console, run the following command. After running the command, add the namespace to your project.
Install-Package AWSSDK
The machine running the client application should be a domain-joined machine. In the client application, you call proxy service to get the temporary credentials and access the S3 data from user folder.