-
Notifications
You must be signed in to change notification settings - Fork 286
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
When using SqlColumnEncryptionAzureKeyVaultProvider with an expired client secret, bizarre error messages and symptoms result #2683
Comments
Have you tried with 5.2.1 ? |
SqlClient 5.2.1 does the same thing. |
Hi @jehhynes thanks for filing this issue. I'm working on reproducing it. In the meantime if you already have a minimal repro you can share that would be much appreciated. |
Hi @mdaigle I could create a minimal repro but it's dependent on a specific state in an external system (i.e. Expired Azure client secret) which I would be unable to share. |
Understood. Even with that limitation it will be helpful to see. |
I haven't been able to reproduce this with straight SqlClient usage. I'm wondering if the issue has something to do with the way that NHibernate is interacting with SqlClient. |
@jehhynes Could you share the repro, please? |
This repro's consistently in my application, but I have not been able to figure out how to reproduce an identical issue outside of my application. I have however reproduced a similar issue. It seems to be caused by a more complex combination of factors than I originally thought. The error is occurring in an ASP.NET Core app, and I think it may have to do with multithreading. Upon further investigation, this error is initially received when rendering a view (using Html.PartialAsync):
Then another database query occurs from an IResultFilter attribute (in OnResultExecuted), which triggers this error:
It seems the first error (which is the expected error) is hidden (presumably due to AspNetCore's multithreaded behavior) and instead the second error is show (which is not expected). Based on these theories, I attempted to create a minimal repro using AspNetCore (attached). Although I wasn't able to get the exact same exception, I did encounter some strange/unexpected behavior/errors so I think it's starting to touch on this issue and may provide you what you need at least to begin troubleshooting. The repro project
Thanks! |
Update:I discovered that by adding a second attribute implementing IResultFilter.OnResultExecuted, we uncover an additional sequence of bizarre exceptions that you can observe by refreshing the page repeatedly: The updated repro project: |
Update 2So I further discovered that by making the ISessionFactory static (instead of rebuilding it with every request) I get a different sequence of errors: This sequence is similar to what I observed in my application - see my StackOverflow question here: The updated repro project: |
Thanks for the repros @jehhynes. I've been working through them and have a couple avenues for investigation. Just to double check, are you running each of these repros with pooling enabled? If you can, can you tell me if the issue still repros when you disable pooling? Thanks! |
If I disable pooling, the bizarre errors go away. |
This is a bug that is leaving connections in an inconsistent state with unread bytes still hanging on the wire. When pooling is enabled, the inconsistent connections are recycled back through to your application and result in undefined error behavior for new connections with the same connection string. The unread bytes off the wire from the last command interfere with the results for the new command. A fix was merged to main last month and it looks like it's slated for the 6.0 release: #2618 |
Hotfixes 5.1.6 and 5.22 have been released! |
@mdaigle @David-Engel
I don't think this is a correct fix - the error message I expect is the |
What I'm seeing is that Here's the sequence of events:
So at the time we drain the data, we've already read all of the bytes for the encrypted column off of the wire or out of the buffer, but we've not incremented the If there's not enough data available, we wait on the socket for more data which will never arrive. This leads to a timeout, which is thrown in place of the column decryption error. |
I have a draft PR here (#2825) that, in local testing, fixes the issue. Using this change with the repro produces the expected error. |
Closing issue as PR has been merged |
When using SqlColumnEncryptionAzureKeyVaultProvider with an expired client secret, the following error is returned:
SqlException: New request is not allowed to start because it should come with valid transaction descriptor.
This error is very confusing and has nothing to do with the actual problem. After seeing this error, we then see the following error on all queries even when column encryption is not enabled on the command:
(Note that the query actually does select
SOME_COLUMN_NAME
)Full stack trace
Expected behavior
I expect a clear error message to be returned which states that column encryption was not possible due to the expired client secret
I do not expect it to "pollute" the connection pool and make all requests to the same database fail with bizarre error messages.
Further technical details
Microsoft.Data.SqlClient version: 5.1.4
.NET target: .NET 8.0
SQL Server version: 2022
Operating system: Windows 11
Additional context
<PackageReference Include="Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider" Version="3.0.0" />
NHibernate 5.5.2
The text was updated successfully, but these errors were encountered: