Amazon Glacier KeyNotFoundException - c#

I keep getting the following exception when trying to upload a file to Amazon Glacier using the .NET sdk:
System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
at Amazon.Glacier.Model.Internal.MarshallTransformations.UploadArchiveResponseUnmarshaller.UnmarshallException(JsonUnmarshallerContext context, Exception innerException, HttpStatusCode statusCode)
at Amazon.Runtime.Internal.Transform.JsonResponseUnmarshaller.UnmarshallException(UnmarshallerContext input, Exception innerException, HttpStatusCode statusCode)
at Amazon.Runtime.AmazonWebServiceClient.handleHttpWebErrorResponse(AsyncResult asyncResult, WebException we)
at Amazon.Runtime.AmazonWebServiceClient.getResponseCallback(IAsyncResult result)
at Amazon.Runtime.AmazonWebServiceClient.endOperation[T](IAsyncResult result)
at Amazon.Glacier.Transfer.Internal.SinglepartUploadCommand.Execute()
at Amazon.Glacier.Transfer.ArchiveTransferManager.Upload(String vaultName, String archiveDescription, String filepath, UploadOptions options)
at UClaim.TaskRunner.Tasks.ArchiveDocuments.Execute() in c:\Projects\uclaim\src\UClaim.TaskRunner\Tasks\ArchiveDocuments.cs:line 55
I've got no idea why it's happening or what it means, and googling is turning up nothing. The code I'm using is nothing special, but here it is for completeness.
var document = GetDocumentToArchive();
var manager = new ArchiveTransferManager(Amazon.RegionEndpoint.EUWest1);
document.ArchiveId = manager.Upload(
"archivedDocs",
string.Format("#{0}: {1}", document.Claim.Id, document.Description),
document.GeneratePathOnServer()).ArchiveId;

Ok turns out this was a stupid mistake. I thought that the SDK would create the vault if it didn't exist but I guess it was attempting to look it up and failing. I logged in to the management console and created the "archivedDocs" vault and now it runs fine

Related

Intermittent ExchangeException when getting EWS mail folders using GetEWSClient in Aspose.Email

I have a Windows service that uses Aspose.Email to call Exchange365 using EWS to read the list of mailbox folders, select a folder and then read the messages. I'm using OAuth Client Credentials authentication.
It works great most of the time but intermittently (around 1-2% of calls) I get an error like this:
ExchangeException: An internal server error occurred. The operation failed.
at #=zJwR5hYhASPjEG51KcFP5cfaNW_E9xKzbKNrDvkouRDML.#=zbEiudxU=(Exception #=zXBxojZA=)
at #=zJwR5hYhASPjEG51KcFP5cfaNW_E9xKzbKNrDvkouRDML.#=zJxs8Enk=()
at Aspose.Email.Clients.Exchange.WebService.EWSClient.#=zeKhM5WV7jZFJ(String #=zwl3m1OEGe_npeTCLKA==, ICredentials #=z8dcYagA=, WebProxy #=zPxR7k20=, #=zobHVK5XZznS2TuzCjFYVkWlb_06X8KyvTg== #=zuLDkIL8cyRRE, #=zLSBmP6s5p40Nd06_7HFvrX6K9S$RdU6i23eiqR0t6nn3VKSIig== #=zPNhWaZtYKy02YJZNn6uibe8=)
at Aspose.Email.Clients.Exchange.WebService.EWSClient.GetEWSClient(String mailboxUri, ICredentials credentials, WebProxy proxy)
at Aspose.Email.Clients.Exchange.WebService.EWSClient.GetEWSClient(String mailboxUri, ICredentials credentials)
at EmailTest.Program.GetFolders(OAuthNetworkCredential credentials) in C:\Dev\Sandbox\EmailTest\Program.cs:line 72
at EmailTest.Program.<Main>d__0.MoveNext() in C:\Dev\Sandbox\EmailTest\Program.cs:line 42
or
ExchangeException: An internal server error occurred. The operation failed.
at #=zRSjcm9RrA3a6zmmitFu34UW3nW4gV823KL6N1k9mXXhY.#=zqfYcQSUW7xkI(WebException #=zMMH$jH0=)
at #=zRSjcm9RrA3a6zmmitFu34UW3nW4gV823KL6N1k9mXXhY.GetResponse()
at System.Web.Services.Protocols.WebClientProtocol.GetWebResponse(WebRequest request)
at System.Web.Services.Protocols.HttpWebClientProtocol.GetWebResponse(WebRequest request)
at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
at #=zKdOmVOFQs9ARtLG3Zlu_IvXd08LXFmI3_5D9s_gr4KsZjsevGw==.FindFolder(FindFolderType FindFolder1)
at #=zKdOmVOFQs9ARtLG3Zlu_ImWGLEjOliBGtOJU8_WNO6d9X7U9LuJoRwA=.#=zthDK7XA=(BaseFolderIdType #=zW0dJQvKwqFVf, String #=z7p_vI0c=)
at #=zKdOmVOFQs9ARtLG3Zlu_ImWGLEjOliBGtOJU8_WNO6d9X7U9LuJoRwA=.#=zthDK7XA=(String #=zxohf2Vezm7Vf, String #=z$vyJZib10Ez_, String #=z7p_vI0c=)
at #=zTAbjhrGUH9E0n8cOeUNrQiqgnbUhJNI_gUj7wuZ$HYDp.ListSubFolders(String #=zxohf2Vezm7Vf, String #=znaKuRg4Rx3vw)
at #=zTAbjhrGUH9E0n8cOeUNrQiqgnbUhJNI_gUj7wuZ$HYDp.ListSubFolders(String #=znaKuRg4Rx3vw)
at EmailTest.Program.GetFolders(OAuthNetworkCredential credentials) in C:\Dev\Sandbox\EmailTest\Program.cs:line 74
at EmailTest.Program.<Main>d__0.MoveNext() in C:\Dev\Sandbox\EmailTest\Program.cs:line 42
If I retry the failing call immediately afterwards, it works fine. So as a workaround I use a "retry" pattern with this call, but I don't like this and I want to know why it's failing. I made a cut-down version of my code for investigation purposes.
Here is how I'm creating the credentials:
private static async Task<OAuthNetworkCredential> GetAccessTokenWithClientCredentials()
{
var app = ConfidentialClientApplicationBuilder
.Create(Settings.ClientId)
.WithTenantId(Settings.TenantId)
.WithClientSecret(Settings.ClientSecret)
.Build();
AuthenticationResult authResult =
await app.AcquireTokenForClient(new[] { Settings.Scopes }).ExecuteAsync().ConfigureAwait(false);
return new OAuthNetworkCredential(Settings.Username, authResult.AccessToken);
}
and here's how I'm calling the folders:
private static string GetFolders(OAuthNetworkCredential credentials)
{
using (IEWSClient client = EWSClient.GetEWSClient(Settings.ExchangeWSUrl, credentials))
{
ExchangeFolderInfoCollection folders = client.ListSubFolders(client.MailboxInfo.RootUri);
return string.Join(", ", folders.Select(x => x.DisplayName));
}
}
This is using Aspose.Email 22.8 and Microsoft.Identity.Client 4.46.2.
ExchangeWSUrl is https://outlook.office365.com/ews/exchange.asmx
Scopes is https://outlook.office.com/.default
If your using the client_credentails flow you need to be using Impersonation and you should be setting the X-AnchorMailbox header to the mailbox you impersonating (I don't use apose but they have an example of it in their docs https://docs.aspose.com/email/net/utility-features/). This affect how a request is routed, that said mailboxes move around in the cloud often so availability is not always guaranteed and you should always expect some requests will fail if the mailbox is being moved.
Update: I haven't changed my code or version of Aspose at all, and the exception doesn't occur anymore.
My feeling is that Microsoft have changed something on the Exchange side to fix the issue, so happy days.

Kubernetes + Redis: The antiforgery token could not be decrypted

I am making use of a Redis database for Data Protection on .net core 3.0 on Kubernetes, but still get the below error. Any ideas?
fail: Microsoft.AspNetCore.Antiforgery.DefaultAntiforgery[7]
An exception was thrown while deserializing the token. Microsoft.AspNetCore.Antiforgery.AntiforgeryValidationException: The
antiforgery token could not be decrypted. --->
System.Security.Cryptography.CryptographicException: The key
{ffb146a1-0e5e-4f96-8566-425f7c2eb99a} was not found in the key ring.
at
Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.UnprotectCore(Byte[]
protectedData, Boolean allowOperationsOnRevokedKeys, UnprotectStatus&
status) at
Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.DangerousUnprotect(Byte[]
protectedData, Boolean ignoreRevocationErrors, Boolean&
requiresMigration, Boolean& wasRevoked) at
Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.Unprotect(Byte[]
protectedData) at
Microsoft.AspNetCore.Antiforgery.DefaultAntiforgeryTokenSerializer.Deserialize(String
serializedToken) --- End of inner exception stack trace --- at
Microsoft.AspNetCore.Antiforgery.DefaultAntiforgeryTokenSerializer.Deserialize(String
serializedToken) at
Microsoft.AspNetCore.Antiforgery.DefaultAntiforgery.GetCookieTokenDoesNotThrow(HttpContext
httpContext)
var redis = ConnectionMultiplexer.Connect(Environment.GetEnvironmentVariable("REDIS_CONNSTR"));
services.AddDataProtection().PersistKeysToStackExchangeRedis(redis, "DataProtection-Keys");
services.AddMvc(options =>
{
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
});
According to the documentation in the below article the application name needs to be set.
services.AddDataProtection()
.PersistKeysToStackExchangeRedis(redis, "DataProtection-Keys")
.SetApplicationName("product");
By default, the Data Protection system isolates apps from one another
based on their content root paths, even if they're sharing the same
physical key repository. This prevents the apps from understanding
each other's protected payloads.
To share protected payloads among apps:
Configure SetApplicationName in each app with the same value.
https://learn.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/overview?view=aspnetcore-3.0
Just a further note on this. If you get a 400 Bad Request and are using an API in the same solution then I would suggest having a look at the IgnoreAntiforgeryToken Attribute to decorate methods where CSRF does not apply.
[HttpPost]
[IgnoreAntiforgeryToken]

Elmah not logging manual errors

Elmah is working alright catching exceptions that are unhandled. However, in one place I am using the following code to manually log error incase a webapi action causes exception. This error is somehow not displayed in elmah.axd wonder why?
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
Here is something I didn't notice earlier, log in debug window:
Exception thrown: 'System.Web.HttpRequestValidationException' in System.Web.dll
System.Web.HttpRequestValidationException (0x80004005): A potentially dangerous Request.Form value was detected from the client (headers="...8241F for <x+152#mail....").
at System.Web.HttpRequest.ValidateString(String value, String collectionKey, RequestValidationSource requestCollection)
at System.Web.HttpRequest.<>c__DisplayClass280_0.<ValidateHttpValueCollection>b__0(String key, String value)
at System.Web.HttpValueCollection.EnsureKeyValidated(String key)
at System.Web.HttpValueCollection.GetValues(Int32 index)
at System.Collections.Specialized.NameValueCollection.Add(NameValueCollection c)
at Elmah.Error.CopyCollection(NameValueCollection collection)
at Elmah.Error..ctor(Exception e, HttpContext context)
at Elmah.ErrorLogModule.LogException(Exception e, HttpContext context)
More Context to the question:
Basically, I have an action method in webapi which parses and processes incoming email parse from sendgrid. If any type of exception occurs, it is manually logged with ELMAH and Application Insights in Azure. Application Insight logging works while ELMAH is failing with the above error message.

Azure Blob Storage (Development Connection Issue)

I have started implementing the Azure Blob storage into my application and when using the development connection string ("UseDevelopmentStorage=true;") it unfortunately fails when trying to create the container here:
The exception is:
Microsoft.WindowsAzure.Storage.StorageException was unhandled by user code
InnerException:
Message=An error occurred while sending the request.
Source=System.Private.CoreLib
InnerException:
HResult=-2147012867
Message=A connection with the server could not be established
Source=System.Private.CoreLib
....
My code:
public async void UploadBlob(IFormFile file, string containerReference, string blobReference)
{
var container = _blobClient.GetContainerReference(containerReference);
await container.CreateIfNotExistsAsync();
var blockBlob = container.GetBlockBlobReference(blobReference);
using (var fileStream = file.OpenReadStream())
{
await blockBlob.UploadFromStreamAsync(fileStream);
}
}
Any ideas why I would not be able to connect?
Thanks, Nik
I had to start the local storage emulator, which I have totally overseen in the tutorial that I looked at. Thank you for your tip Kenneth!
See here:
https://azure.microsoft.com/en-us/documentation/articles/storage-use-emulator/#authenticating-requests-against-the-storage-emulator

How Can I Get XSockets to Work With HTTPS and WSS?

My XSockets.Net code works fine when I use a "ws://" URL, but when I try to implement a secure version, I can't get it to work.
I used the following C# example code as my guide:
//Sample 1 - Certificate from store public class ChuckNorrisConfig :
ConfigurationSetting {
public MyCustomConfig1() : base(new Uri("wss://my.server.ip.address:4502"))
{
this.CertificateLocation = StoreLocation.LocalMachine;
this.CertificateSubjectDistinguishedName = "cn=localmachine";
}
}
//Sample 2 - X509Certificate2
public class MyCustomConfig2 : ConfigurationSetting {
public ChuckNorrisConfig() : base(new Uri("wss://my.server.ip.address:4502"))
{
this.Certificate = new X509Certificate2("file.name", "password");// line 369
}
}
I get the following error:
ERROR 2014/09/07-19:50:16 Could not start XSockets server.
System.Reflection.TargetInvocationException: Exception has been thrown
by the target of an invocation. --->
System.Security.Cryptography.CryptographicException: The system cannot
find the file specifed.
at
System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32
hr) at
System.Security.Cryptography.X509Certificates.X509Utils._QueryCertFileType(String
fileName) at
System.Security.Cryptography.X509Certificates.X509Certificate.LoadCertificateFromFile(String
fileName, Object password, X509KeyStorageFlags keyStorageFlags) at
System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(String
fileName, String password) at NET.Server.MyCustomConfig2..ctor() in
C:\MyProjects\NET.Server\Program.cs:line 369 --- End of
inner exception stack trace ---
It errors out on the line 369 which I've tagged with the comment.
I don't know what "file.name" is supposed to be. How do I get the "file.name" of an SSL certificate? I've been using a self-signed test certificate I made, but I don't know where to get its "file.name"
I wish there was an actual example of runnable code which I could reference, rather than having to look at generic stuff.
Does anyone have a full example of a working XSockets WSS implementation? I am using XSockets.Net version 3.0.6, thanks.
If you have the cert installed on the machine you need you use Sample1 (sounds like this is what you are looking for).
You can find the certificate in your computer using certmanager certmgr.msc and find it by name.
Sample 1 is in case you have the actual file certificate and dont want to import it.

Categories