Securing Amazon’s Simple Storage Objects for download using Urls with expiry period

The C# code sample below demonstrates how to make your Amazon's Simple Storage object urls secure with expiry period.

In the era of internet, content security for private and copyright content uploaded, is the cause of concern for the individuals and organizations. The security of the downloadable content with restrictions on web portals and websites, has made many developers think twice before they put the content on various storage locations.

Amazon S3 is storage for the Internet. It is designed to make web-scale computing easier for developers. Amazon S3 provides a simple web services interface that can be used to store and retrieve any amount of data, at any time, from anywhere on the web. It gives any developer access to the same highly scalable, reliable, secure, fast, inexpensive infrastructure that Amazon uses to run its own global network of web sites. The service aims to maximize benefits of scale and to pass those benefits on to developers.

Securing the download links on S3 with encryption and expiry time using .Net:

Amazon simple storage service provides an option to make your upload content’s download url secure by making use of encryption algorithm and expiry period set as per your discretion. To make your urls secure on Amazon S3, you need to follow the following methods:

Method 1: Using AWS SDK for .NET

1. Download Amazon’s AWS SDK for .NET from http://aws.amazon.com/developers/getting-started/net/
2. Add reference to your .Net project
3. Create an instance of the AmazonS3 class by providing your AWS credentials. These credentials are used in creating a signature for authentication when you generate a pre-signed URL.
4. Execute the AmazonS3.GetPreSignedURL method to generate a pre-signed URL.

//Sample code using C#

using System;
using Amazon.S3;
using Amazon.S3.Model;

namespace s3amazon.SecureUrl
{
class GetSecureURL
{
static string bucket ="XXXXX--bucket name in which S3 object is stored---XXXX";
static string keyName = "XXXXX--- S3 object name----XXXXX";
static IAmazonS3 s3Client;

public static string GetSecuredUrl()
{
using (s3Client = new AmazonS3Client (Amazon.RegionEndpoint.USEast1))
{
string urlString = GetSignedURL();
}
}


private static string GetSignedURL()
{
string urlString = "";
GetPreSignedUrlRequest signedRequest = new GetPreSignedUrlRequest
{
BucketName = bucketName,
Key = keyName,
Expires = DateTime.Now.AddMinutes(5) // Set expiry of 5 minutes

};

try
{
urlString = s3Client.GetPreSignedURL(signedRequest);
}
catch (AmazonS3Exception amazonS3Exception)
{
if (amazonS3Exception.ErrorCode != null && (amazonS3Exception.ErrorCode.Equals("InvalidAccessKeyId")
||amazonS3Exception.ErrorCode.Equals("InvalidSecurity")))
{
//Handle Exception accordinlgy
}
else
{
//Handle Exception accordinlgy
}
}
catch (Exception e)
{
//Handle Exception accordinlgy
}
return urlString;
}
}
}


Method 2: Using ThreeSharpWrapper.cs
1. Download ThreeSharpWrapper.cs from http://threesharp.codeplex.com/
2. Add this to your .Net project:

/*******************************************************************************
* Licensed under the Apache License, Version 2.0 (the "License");
*
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0.html
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
* *****************************************************************************
*
* Joel Wetzel
* Affirma Consulting
* jwetzel@affirmaconsulting.com
*
*/

using System;
using System.Collections.Generic;
using System.Text;
using Affirma.ThreeSharp.Model;
using Affirma.ThreeSharp.Query;
using System.Collections;

namespace Affirma.ThreeSharp.Wrapper
{
/// <summary>
/// Wraps basic functionality of the ThreeSharp Library into single-line commands
/// </summary>
public class ThreeSharpWrapper
{
private ThreeSharpConfig config;
private IThreeSharp service;

public ThreeSharpWrapper(String awsAccessKeyId, String awsSecretAccessKey)
{
this.config = new ThreeSharpConfig();
this.config.AwsAccessKeyID = awsAccessKeyId;
this.config.AwsSecretAccessKey = awsSecretAccessKey;

this.service = new ThreeSharpQuery(this.config);
}

/// <summary>
/// Adds a bucket to an S3 account
/// </summary>
public void AddBucket(String bucketName)
{
BucketAddRequest bucketAddRequest = new BucketAddRequest(bucketName);
BucketAddResponse bucketAddResponse = this.service.BucketAdd(bucketAddRequest);
bucketAddResponse.DataStream.Close();
}

/// <summary>
/// Returns a string of XML, describing the contents of a bucket
/// </summary>
public String ListBucket(String bucketName)
{
BucketListRequest bucketListRequest = new BucketListRequest(bucketName);
BucketListResponse bucketListResponse = this.service.BucketList(bucketListRequest);
return bucketListResponse.StreamResponseToString();
}

/// <summary>
/// Adds a string to a bucket, as an object
/// </summary>
public void AddStringObject(String bucketName, String keyName, String data)
{
ObjectAddRequest objectAddRequest = new ObjectAddRequest(bucketName, keyName);
objectAddRequest.LoadStreamWithString(data);
ObjectAddResponse objectAddResponse = this.service.ObjectAdd(objectAddRequest);
objectAddResponse.DataStream.Close();
}

/// <summary>
/// Streams a file to a bucket as an object
/// </summary>
public void AddFileObject(String bucketName, String keyName, String localfile)
{
ObjectAddRequest objectAddRequest = new ObjectAddRequest(bucketName, keyName);
SortedList headers = new SortedList();
headers.Add("x-amz-acl", "public-read");
objectAddRequest.Headers = headers;
objectAddRequest.LoadStreamWithFile(localfile);

ObjectAddResponse objectAddResponse = this.service.ObjectAdd(objectAddRequest);
objectAddResponse.DataStream.Close();
}

public void AddImageObject(String bucketName, String keyName, String localfile)
{
ObjectAddRequest objectAddRequest = new ObjectAddRequest(bucketName, keyName);
SortedList headers = new SortedList();
headers.Add("x-amz-acl", "public-read");
headers.Add("Cache-Control", "max-age=31536000");
// headers.Add("Expires", DateTime.Today.AddDays(365).GetDateTimeFormats()[104]);
objectAddRequest.Headers = headers;
objectAddRequest.LoadStreamWithFile(localfile);

ObjectAddResponse objectAddResponse = this.service.ObjectAdd(objectAddRequest);
objectAddResponse.DataStream.Close();
}

public void AddPlayerXmlObject(String bucketName, String keyName, String localfile)
{
ObjectAddRequest objectAddRequest = new ObjectAddRequest(bucketName, keyName);
SortedList headers = new SortedList();
headers.Add("x-amz-acl", "public-read");
headers.Add("Expires", DateTime.Today.AddHours(1));
objectAddRequest.Headers = headers;
objectAddRequest.LoadStreamWithFile(localfile);

ObjectAddResponse objectAddResponse = this.service.ObjectAdd(objectAddRequest);
objectAddResponse.DataStream.Close();
}

public void AddPPSXObject(String bucketName, String keyName, String localfile)
{
ObjectAddRequest objectAddRequest = new ObjectAddRequest(bucketName, keyName);
SortedList headers = new SortedList();
headers.Add("x-amz-acl", "public-read");
headers.Add("Content-Type", "application/vnd.openxmlformats-officedocument.presentationml.slideshow");
objectAddRequest.Headers = headers;
objectAddRequest.LoadStreamWithFile(localfile);

ObjectAddResponse objectAddResponse = this.service.ObjectAdd(objectAddRequest);
objectAddResponse.DataStream.Close();
}

public void AddPPTXObject(String bucketName, String keyName, String localfile)
{
ObjectAddRequest objectAddRequest = new ObjectAddRequest(bucketName, keyName);
SortedList headers = new SortedList();
headers.Add("x-amz-acl", "public-read");
headers.Add("Content-Type", "application/vnd.openxmlformats-officedocument.presentationml.presentation");
objectAddRequest.Headers = headers;
objectAddRequest.LoadStreamWithFile(localfile);

ObjectAddResponse objectAddResponse = this.service.ObjectAdd(objectAddRequest);
objectAddResponse.DataStream.Close();
}

/// <summary>
/// Streams a file to a bucket as an object, with encryption
/// </summary>
public void AddEncryptFileObject(String bucketName, String keyName, String localfile, String encryptionKey, String encryptionIV)
{
ObjectAddRequest objectAddRequest = new ObjectAddRequest(bucketName, keyName);
objectAddRequest.LoadStreamWithFile(localfile);
objectAddRequest.EncryptStream(encryptionKey, encryptionIV);
ObjectAddResponse objectAddResponse = this.service.ObjectAdd(objectAddRequest);
objectAddResponse.DataStream.Close();
}

/// <summary>
/// Gets a file object from a bucket, and streams it to disk
/// </summary>
public void GetFileObject(String bucketName, String keyName, String localfile)
{
ObjectGetRequest objectGetRequest = new ObjectGetRequest(bucketName, keyName);
ObjectGetResponse objectGetResponse = this.service.ObjectGet(objectGetRequest);
objectGetResponse.StreamResponseToFile(localfile);
}

/// <summary>
/// Gets a file object from a bucket, streaming it to disk, with decryption
/// </summary>
public void GetDecryptFileObject(String bucketName, String keyName, String localfile, String encryptionKey, String encryptionIV)
{
ObjectGetRequest objectGetRequest = new ObjectGetRequest(bucketName, keyName);
ObjectGetResponse objectGetResponse = this.service.ObjectGet(objectGetRequest);
objectGetResponse.DecryptStream(encryptionKey, encryptionIV);
objectGetResponse.StreamResponseToFile(localfile);
}

/// <summary>
/// Generates a URL to access an S3 object in a bucket
/// </summary>
public String GetUrl(String bucketName, String keyName)
{
UrlGetRequest urlGetRequest = new UrlGetRequest(bucketName, keyName);
urlGetRequest.ExpiresIn = 60 * 1000;
UrlGetResponse urlGetResponse = this.service.UrlGet(urlGetRequest);
return urlGetResponse.StreamResponseToString();
}

/// <summary>
/// Deletes an object from a bucket
/// </summary>
public void DeleteObject(String bucketName, String keyName)
{
ObjectDeleteRequest objectDeleteRequest = new ObjectDeleteRequest(bucketName, keyName);
ObjectDeleteResponse objectDeleteResponse = service.ObjectDelete(objectDeleteRequest);
objectDeleteResponse.DataStream.Close();
}

/// <summary>
/// Deletes a bucket from an S3 account
/// </summary>
public void DeleteBucket(String bucketName)
{
BucketDeleteRequest bucketDeleteRequest = new BucketDeleteRequest(bucketName);
BucketDeleteResponse bucketDeleteResponse = service.BucketDelete(bucketDeleteRequest);
bucketDeleteResponse.DataStream.Close();
}
}
}


//Sample Code to encrypt your URLs using GetUrl method:

#region [Method to get download url]
/// <summary>
/// Method to get download url
/// </summary>
/// <returns></returns>
public string GetDownloadurl()
{
ThreeSharpWrapper amazonWrapper = new ThreeSharpWrapper(this._awsAccessKey, this._awsSecretAccessKey);
return amazonWrapper.GetUrl(this._bucketName, this._keyName);
}
#endregion

You can use the above give code to make your URLs for Amazon’s S3 objects secure with expiry period set as per your discretion.

By Sushil Kumar   Popularity  (1846 Views)