How to use signatureVersion on AmazonS3Config? - c#

I have next error:
"The authorization mechanism you have provided is not supported. Please use AWS4-HMAC-SHA256."
When I try download a file from my bucket on Amazon S3. My code is the next:
AmazonS3Config config = new AmazonS3Config();
config.CommunicationProtocol = Protocol.HTTP;
config.RegionEndpoint = Amazon.RegionEndpoint.USEast1;
AmazonS3Client s3Client = new AmazonS3Client("MyAccesKeyAWS", "MyAccesSecretAWS", config);
TransferUtility transfer = new TransferUtility(s3Client);
TransferUtilityDownloadRequest downloader = new TransferUtilityDownloadRequest();
downloader.BucketName = "bucketName";
downloader.FilePath = "MyPath\\To\\Local\\File\\";
downloader.Key = "NameFile.pdf";
transfer.Download(downloader); //<-- here the ERROR:
this generete the next error: The authorization mechanism you have provided is not supported. Please use AWS4-HMAC-SHA256.
I was reasearch it on google and on some blogs.
some suggest using the property "signature version" to v4.
something like...
config.signatureVersion = "v4";
but my config object, not have this property.
any suggestion?
thank you!!!

Try This Code
AmazonS3Config config = new AmazonS3Config();
string accessKey = WebConfigurationManager.AppSettings["AWSaccessKey"].ToString();
string secretKey = WebConfigurationManager.AppSettings["AWSsecretKey"].ToString();
config.ServiceURL = WebConfigurationManager.AppSettings["AWSServiceURL"].ToString();
string storageContainer = WebConfigurationManager.AppSettings["AWSBucketName"].ToString();
AmazonS3Client client2 = new AmazonS3Client(
accessKey,
secretKey,
config
);
Amazon.S3.AmazonS3 client3 = Amazon.AWSClientFactory.CreateAmazonS3Client(accessKey, secretKey, config);
GetObjectRequest request1 = new GetObjectRequest();
request1.BucketName = storageContainer;
request1.WithBucketName(storageContainer);
request1.WithKey(originalfileName);
GetObjectResponse response1 = client3.GetObject(request1);
using (Stream responseStream = response1.ResponseStream)
{
var bytes = ReadStream(responseStream);
var download = new FileContentResult(bytes, "application/pdf");
download.FileDownloadName = response1.Key;
int c = filePath.Split('/').Length;
byte[] fileBytes = download.FileContents;
//return download;
var fileEntry = new ZipEntry(filePath.Split('/')[c - 1].ToString());
zipStream.PutNextEntry(fileEntry);
zipStream.Write(fileBytes, 0, fileBytes.Length);
}
zipStream.Flush();
zipStream.Close();

Related

Cant correct upload file it says no file found for upload

im trying to create method who can upload file from special path to API link, but when i run application its says no file for upload has been added, so i cant understand, where is problem, i think maybe this line is not working correct bellow
requestUploadFileToDocument.GetRequestStream().Write(data, 0, data.Length);
My full code for method
var ConKey = ConfigurationManager.AppSettings["ConKey"];
var AddFile = ConfigurationManager.AppSettings["AddFile"];
var Document_IDSTflow = ConfigurationManager.AppSettings["Document_IDSTflow"];
var file = ConfigurationManager.AppSettings["file"];
string UploadFileToDocumentUrl = String.Format(AddFile + "Document_ID=" + Document_IDSTflow + "&key=" + ConKey);
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] data = encoder.GetBytes(file);
HttpWebRequest requestUploadFileToDocument = WebRequest.Create(UploadFileToDocumentUrl) as HttpWebRequest;
requestUploadFileToDocument.Method = "POST";
requestUploadFileToDocument.ContentType = "multipart/form-data";
requestUploadFileToDocument.ContentLength = data.Length;
requestUploadFileToDocument.GetRequestStream().Write(data, 0, data.Length);
var httpResponse = (HttpWebResponse)requestUploadFileToDocument.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result2 = streamReader.ReadToEnd();
DocumentInfo DocumentInfoJsonData = JsonConvert.DeserializeObject<DocumentInfo>(result2);
if (DocumentInfoJsonData.Status.IsRequestSuccessful == true)
{
Console.WriteLine("Metode (POST) - OK");
}
else
{
Console.WriteLine("Metode (POST) - ERROR");
Console.WriteLine("\n" + "Error info: " + result2 + "\n");
}
}
Okey, i resolve this by my self after some wasted days :D
HttpClient client = new HttpClient();
MultipartFormDataContent form = new MultipartFormDataContent();
HttpContent content = new StringContent("fileToUpload");
form.Add(content, "fileToUpload");
var stream = new FileStream(FileLocation, FileMode.Open);
content = new StreamContent(stream);
content.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = DocName,
FileName = FileNameExtension
};
form.Add(content);
HttpResponseMessage response = null;
response = client.PostAsync(UploadFileToDocumentUrl, form).Result;

How do you decrypt blobs with Azure KeyVault keys in Azure.Storage v12

Our code is currently using the old Microsoft.WindowsAzure.Storage libraries for blob storage access in Azure. I am trying to use the new v12 Azure.Storage.Blobs libraries to replace the old ones, however I cannot figure out how to decrypt/encrypt the blobs. The MS docs (https://learn.microsoft.com/en-us/azure/storage/blobs/storage-encrypt-decrypt-blobs-key-vault?tabs=dotnet) helpfully say that the v12 code snippets aren't ready yet, so there are no code examples.
The old code is like this:
var tokenProvider = new AzureServiceTokenProvider();
var cloudResolver = new KeyVaultKeyResolver(
new KeyVaultClient.AuthenticationCallback(_tokenProvider.KeyVaultTokenCallback));
var encryptionThingy = await cloudResolver.ResolveKeyAsync(<Key Vault URL> + "/keys/" + <key name>, CancellationToken.None);
var policy = new BlobEncryptionPolicy(encryptionThingy, cloudResolver);
var options = new BlobRequestOptions() { EncryptionPolicy = policy };
await <ICloudBlob Instance>.DownloadToStreamAsync(<stream>, null, options, null);
So far with the new code I've gotten here:
var azureKeys = new KeyClient(new Uri(<key vault url>), new DefaultAzureCredential());
var encKey = azureKeys.GetKey(<key name>);
ClientSideEncryptionOptions encryptionOptions = new ClientSideEncryptionOptions(ClientSideEncryptionVersion.V1_0)
{
KeyEncryptionKey = (IKeyEncryptionKey)key
};
var bsClient = new BlobServiceClient(cStr, new SpecializedBlobClientOptions() { ClientSideEncryption = encryptionOptions });
var containerClient = new BlobContainerClient(cStr, containerName);
bClient = containerClient.GetBlobClient(<blob name>);
Of course this throws an exception because KeyVaultKey cannot be converted to IKeyEncryptionKey. So my questions are
Can the key be converted to an IKeyEncryptionKey easily, and how?
Can a key resolver be easily retrieved from the Azure SDKs, and how so?
I'm presuming there are ways to do this that don't involve creating our own implementations of the interfaces, but MS in their infinite wisdom didn't see fit to add those few lines to their documentation.
I write a simple demo for you. Just try the C# console app below about azure blob client-encryption with azure KeyVault:
using System;
using Azure.Identity;
using Azure.Security.KeyVault.Keys.Cryptography;
using Azure.Storage;
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Specialized;
namespace BlobEncyptionWithBlob
{
class Program
{
static void Main(string[] args)
{
string keyVaultName = "";
string keyName = "";
string kvUri = "https://" + keyVaultName + ".vault.azure.net/keys/" + keyName;
string storageConnStr = "";
string containerName = "";
string encyptBlob = "encypt.txt";
string localblobPath = #"C:\Users\Administrator\Desktop\123.txt";
string localblobPath2 = #"C:\Users\Administrator\Desktop\123-decode.txt";
//Below is to use recommended OAuth2 approach
//string clientID = "<OAuth Client ID>";
//string clientSecret = "<OAuth Secret>";
//string tenant = "<OAuth Tenant ID>";
//var cred = new ClientSecretCredential(tenant, clientID, clientSecret);
//This is what you use to directly replace older AppAuthentication
var cred = new DefaultAzureCredential();
CryptographyClient cryptoClient = new CryptographyClient(new Uri(kvUri), cred);
KeyResolver keyResolver = new KeyResolver(cred);
ClientSideEncryptionOptions encryptionOptions = new ClientSideEncryptionOptions(ClientSideEncryptionVersion.V1_0)
{
KeyEncryptionKey = cryptoClient,
KeyResolver = keyResolver,
KeyWrapAlgorithm = "RSA-OAEP"
};
BlobClientOptions options = new SpecializedBlobClientOptions() { ClientSideEncryption = encryptionOptions };
var blobClient = new BlobServiceClient(storageConnStr,options).GetBlobContainerClient(containerName).GetBlobClient(encyptBlob);
//upload local blob to container
blobClient.Upload(localblobPath);
//If you want to modify the meta data you have to copy the exisiting meta, think there is a bug in the library that will wipe out the encryptiondata metadata if you write your own meta
var myMeta = new Dictionary<string, string>();
myMeta.Add("comment", "dis file is da shiznit");
foreach (var existingMeta in blobClient.GetProperties().Value.Metadata)
{
if (!myMeta.ContainsKey(existingMeta.Key))
{
myMeta.Add(existingMeta.Key, existingMeta.Value);
}
}
blobClient.SetMetadata(myMeta);
//Download from container to see if it is decided
blobClient.DownloadTo(localblobPath2);
}
}
}
Result:
My local .txt file content:
Upload to blob and its content, it has been encrypted :
Download to local again and its content, it has been decoded:

How do I delete a file in S3 with C#?

I am trying to delete a file in S3 using C# code:
string _bucketName = "mybucket-ap-southeast-1-123627123717";
string _filename "ronaldo.png";
AmazonS3Config _config = new AmazonS3Config();
_config.ServiceURL = HOSTNAME + _bucketName;
IAmazonS3 _client = new AmazonS3Client(ACCESS_KEY, ACCESS_SECRET, _config);
await _client.DeleteObjectAsync(
new Amazon.S3.Model.DeleteObjectRequest { BucketName = _bucketName, Key = _fileName });
The code does not throw any exception or error, but when I check and refresh the AWS S3 Management console the file is still there! What have I missed?
IAmazonS3 s3Client = new AmazonS3Client(_appConfiguration["AWS:AccessKey"], _appConfiguration["AWS:SecretKey"], RegionEndpoint.USEast1);
var deleteObjectRequest = new DeleteObjectRequest { BucketName = "BucketName ", Key = "key"};
s3Client.DeleteObjectAsync(deleteObjectRequest).Wait();
IAmazonS3 _client1 = new AmazonS3Client(AwsAccessKeyId, AwsSecretKey, RegionEndpoint.APSouth1);
var deleteRequest = new DeleteObjectRequest
{
Key = YourFolderName/YourFileName,
BucketName = YourBucketName,
};
await _client1.DeleteObjectAsync(deleteRequest);
Use this its working fine

Upload file Amazon S3 return The stream does not support concurrent IO read or write operations

I try upload file in amazon s3, but always return this message.
My code:
AmazonS3Config S3Config = new AmazonS3Config()
{
ServiceURL = "s3.amazonaws.com",
CommunicationProtocol = Protocol.HTTP,
RegionEndpoint = RegionEndpoint.SAEast1
};
using (AmazonS3Client client = new AmazonS3Client(KEY_S3, PASSWORD, S3Config))
{
string pathInS3 = folder + "/" + fileName;
PutObjectRequest request = new PutObjectRequest();
request.WithBucketName(BUCKET_NAME);
request.WithKey(pathInS3);
request.WithInputStream(memoryStreamFile);
request.CannedACL = S3CannedACL.PublicReadWrite;
client.PutObject(request);
}
I had use lock in request and client but do not resolve.
I think the problem is the memoryStreamFile, please do double check trying to read the content of your memorystreamFile.So another way to upload files to AmazonS3 with C# is the following:
AmazonS3Config cfg = new AmazonS3Config();
cfg.RegionEndpoint = Amazon.RegionEndpoint.EUCentral1;// region endpoint
string bucketName = "your bucket";
AmazonS3Client s3Client = new AmazonS3Client("your access key", "your secret key", cfg);
string dataString ="your data ";
MemoryStream data = new System.IO.MemoryStream(UTF8Encoding.ASCII.GetBytes(dataString));
TransferUtility t = new TransferUtility(s3Client);
t.Upload(data, bucketName, "testUploadFromTransferUtility.txt");

Getting file url after upload amazon s3

I need to get file url after upload the file to amazons3 server.
Here is my upload code.
How to return amazons3 path ?
public static bool UploadToS3(string bucketName, string bucketFilePath, Byte[] localPath)
{
var client = Amazon.AWSClientFactory.CreateAmazonS3Client(Config.EmailServer.AwsAccessKey, Config.EmailServer.AwsSecretKey, Amazon.RegionEndpoint.EUWest1);
PutObjectRequest request = new PutObjectRequest()
{
BucketName = bucketName,
Key = bucketFilePath,
InputStream = new MemoryStream(localPath),
AutoCloseStream = true,
CannedACL = S3CannedACL.PublicRead,
StorageClass = S3StorageClass.ReducedRedundancy
};
PutObjectResponse response = client.PutObject(request);
return true;
}
Simply you can generate download expiry link after upload completed.
example:
var expiryUrlRequest = new GetPreSignedUrlRequest()
.WithBucketName(BucketName)
.WithKey(Key)
.WithExpires(DateTime.Now.AddDays(10));
string url = _amazonS3Client.GetPreSignedURL(expiryUrlRequest);
Try this method
GetPreSignedUrlRequest request = new GetPreSignedUrlRequest();
request.BucketName = "my-bucket-name";
request.Key = "secret_plans.txt";
request.Expires = DateTime.Now.AddHours(1);
request.Protocol = Protocol.HTTP;
string url = client.GetPreSignedURL(request);
Console.WriteLine(url);

Categories

Resources