I have an RDS instance running Postgres which has IAM Authentication enabled. I can successfully connect using an IAM token via powershell, but I'm having trouble with certificates when trying to connect using the Npgsql library with C# (targeting .Net Core 3.1) from Visual Studio 2019 Version 16.8.5 (on .Net Framework 4.8).
Note, I've been referencing this AWS page, which gives download links for the certificates.
https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.SSL.html
I've also been referencing this page to guide me through getting this set up.
https://aws.amazon.com/premiumsupport/knowledge-center/rds-postgresql-connect-using-iam/
I can connect with PowerShell, using:
$ENV:RDSHOST="my-postgres-instance.eu-west-1.rds.amazonaws.com"
$ENV:PGPASSWORD="$(aws rds generate-db-auth-token --hostname $ENV:RDSHOST --port 5432 --region eu-west-1 --username my_db_user)"
psql -h $ENV:RDSHOST -p 5432 "sslmode=verify-full sslrootcert=rds-ca-2019-root.pem dbname=my_db user=my_db_user password=$ENV:PGPASSWORD"
However when I try to open a connection with C# using the Npgsql library with the code below, I get an exception:
var host = "my-postgres-instance.eu-west-1.rds.amazonaws.com";
var port = 5432;
var user = "my_db_user";
var token = RDSAuthTokenGenerator.GenerateAuthToken(RegionEndpoint.EUWest1, host, port, user);
var builder = new NpgsqlConnectionStringBuilder
{
Host = host,
Port = port,
Database = "my_db",
Username = user,
Password = token,
SslMode = SslMode.Require,
RootCertificate = #"C:\Path\To\Cert\rds-combined-ca-bundle.pem",
};
using (var conn = new NpgsqlConnection(builder.ConnectionString))
{
conn.Open();
}
Npgsql.NpgsqlException: 'Exception while performing SSL handshake
AuthenticationException: The remote certificate is invalid according to the validation procedure.
It's worth noting that I can connect setting TrustServerCertificate = true, however as I understand it, this is masking the problem and reducing security, and is not advisable.
The AWS page linked above mentions:
If your application is on Microsoft Windows and requires a PKCS7 file, you can download the PKCS7 certificate bundle. This bundle contains both the intermediate and root certificates at https://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.p7b.
I've tried specifying this p7b file as the NpgsqlConnectionStringBuilder.ClientCertificate, but this causes a different exception when opening the connection:
Internal.Cryptography.CryptoThrowHelper.WindowsCryptographicException: 'Cannot find the original signer.'
Anyone able to help me understand how to connect? It's worth noting that I'm not very familiar with detting up SSL connections or dealing with certificates, so bear that in mind.
Related
I have a SQL server version 12.0.6205 and the following code in a .Net Core 3.1 (or 6) Web Api controller:
var builder = new SqlConnectionStringBuilder
{
DataSource = DataSource,
UserID = UserID,
Password = Password,
InitialCatalog = InitialCatalog,
ApplicationIntent = ApplicationIntent.ReadWrite,
// Same result if true/true
Encrypt = false,
TrustServerCertificate = false
};
var connection = new SqlConnection(builder.ToString());
using (var cmd = new SqlCommand() { Connection = connection, CommandText = "SELECT TOP 1 * FROM [dbo].[Table]" })
{
connection.Open(); // Breaks here
var reader = cmd.ExecuteReader();
Console.WriteLine(reader.HasRows);
}
Locally this code works without issues but when executing in Azure's App service it breaks when opening the connection with:
System.Data.SqlClient.SqlException (0x80131904): A connection was successfully established with the server, but then an error occurred during the pre-login handshake. (provider: SSL Provider, error: 31 - Encryption(ssl/tls) handshake failed)
I also have been able to reproduce the error, locally, if creating
a docker imaged based on appsvc/dotnetcore (any tag)
FROM mcr.microsoft.com/appsvc/dotnetcore:3.1-latest_20220105.1
ENV ASPNETCORE_URLS=http://+:80
EXPOSE 8080
WORKDIR /home/site/wwwroot/
COPY . .
ENTRYPOINT ["dotnet", "Test.dll"]
Like #DraggonDragger said this is a TLS issue but in my specific case I can't rely on the SQL server being updated to allow TLS 1.2 therefore I had to allow TLS 1.0 in the application.
I ended up following this answer: https://stackoverflow.com/a/61523341/17892120;
Essentially, for docker images, adding this line is enough:
RUN sed -i 's/DEFAULT#SECLEVEL=2/DEFAULT#SECLEVEL=1/g' /etc/ssl/openssl.cnf
And for Azure's App Service, we can add
sed -i 's/DEFAULT#SECLEVEL=2/DEFAULT#SECLEVEL=1/g' /etc/ssl/openssl.cnf && dotnet Test.dll for the startup command.
For future reference, there's also a discussion about this in GitHub, link.
Found a similar issue in GitHub which is TLS HandShake Failure in SQL Server Pre-Login Handshake with Docker Image.
Also, This error typically occurs in client environments like docker image containers, Unix clients, or Windows clients where TLS 1.2 is the minimum supported TLS protocol.
Install the latest updates on supported versions of SQL Server1 and ensure the TLS 1.2 protocol is enabled on the server.
Install the target SQL Server's TLS/SSL certificate in the client environment. It will be validated if encryption is needed.
Set the "Trust Server Certificate = true" property in the connection string.
Generate a new TLS/SSL Certificate for the server whose hash is signed with at-least the SHA-256 hashing algorithm.
Reference: Pre-Login Handshake Error Solution from Microsoft
I wanted to give a elastic cloud a try today, but I can't seem to connect from c# app. Everything is working fine with locally deployed version but with cloud I'm always getting this error.
I deployed it to azure (free trial thing).
NEST client version is 7.14
.net 5.0
Error:
The client is unable to verify that the server is Elasticsearch due to an unsuccessful product check call. Some functionality may not be compatible if the server is running an unsupported product
Error2:
Authentication failed because the remote party sent a TLS alert: 'HandshakeFailure'.
this is how I'm setting up client
var cloudId = "cloudid:xxxxxxxx";
var credentials = new BasicAuthenticationCredentials("elastic", "xxxxxxxxxxxx");
var pool = new CloudConnectionPool(cloudId, credentials);
var settings = new ConnectionSettings(pool)
.ThrowExceptions()
.EnableDebugMode();
var client = new ElasticClient(settings);
Looks like an issue with OS, as I'm using Windows 11 Preview as same code is working on Ubuntu 20.04 and Windows server.
When I use the .NET connector with my console application ( .NET 4.7.2) to connect to a remote MySQL server I get the error below.
MySql.Data.MySqlClient.MySqlException (0x80004005): Authentication to host 'XX.XXX.XXX.XX' for user 'YYYYYYY' using method 'mysql_native_password' failed with message: Access denied for user 'YYYYYYY'#'ZZZ.ZZZ.ZZZ.ZZZ' (using password: YES) ---> MySql.Data.MySqlClient.MySqlException (0x80004005): Access denied for user 'YYYYYYY'#'ZZZ.ZZZ.ZZZ.ZZZ' (using password: YES)
I thought it has to do with the password and reset it and it still didn't work, have been able to connect to it successfully using "HeidiSQL" and "MYSQL Workbench" and so there doesn't seem to be any problem with password perse at the server end.
Please note that I am using MySQL with SSL connection as demonstrated by sample code below.
var builder = new MySqlConnectionStringBuilder();
builder.Server = "XX.XXX.XXX.XX";
builder.UserID = "YYYYYYY";
builder.Password = "PPPPPPPPPPP";
builder.SslCa = #"D:\certs\server-ca.pem";
builder.SslKey = #"D:\certs\client-key.pem";
builder.SslCert = #"D:\certs\client-cert.pem";
builder.SslMode = MySqlSslMode.VerifyFull;
builder.Database = "noodlewatch";
builder.Port = 3306;
builder.Pooling = true;
builder.UseCompression = true;
MySqlConnection conn = new MySqlConnection(builder.ConnectionString);
Any ideas on what needs to be done here?
I have tried a lot of permutations and combinations with the "MySqlConnectionStringBuilder" but it always ends the same way. It definitely is not a "password" issue as I can connect to it with standard MySQL clients.
Edit:
This is not a duplicate of that other question with a similar error because that one had to do with user grants, I am able to connect to the same remote server with "HeidiSQL" and "MySQL Workbench" from the same client machine so it's quite obviously not something to do with privilege issues for the user.
Edit:
The . NET application and the other client applications are residing on the same Windows 10 machine.
I've seen a lot of discussion about "TF400324: Team Foundation services are not available from server", but everything I've read relates to DNS or proxies, and reflect being unable to connect to TFS at all, through any channel. My case is different: I cannot reach my TFS server when using the .NET library, but it works fine using Visual Studio's workflow tools, and I can reach the same URL just fine in a browser.
Zee code, it is here:
private TfsConfigurationServer _server;
...
Uri url = new Uri(serverName + rootFolder);
var creds1 = new NetworkCredential(username, password, Environment.UserDomainName);
var creds2 = new BasicAuthCredential(creds1);
var creds3 = new TfsClientCredentials(creds2) { AllowInteractive = false };
_server = new TfsConfigurationServer(url, creds3);
// Throws Microsoft.TeamFoundation.TeamFoundationServiceUnavailableException
_server.Authenticate();
The creds are needlessly elaborate because I've tried various suggested solutions, but I don't think that's relevant; I get the same behavior with any other creds I've tried, or no creds at all.
If I copy the exact URL to a browser, I can authenticate and proceed. Within Visual Studio I can connect to TFS using Source Control Explorer and other tools, without explicitly authenticating. What might the library want handled differently?
Additional detail from the error:
Team Foundation services are not available from server https://tfs.imahufflepuff.com:8080/tfs/Root/Project.
Technical information (for administrator):
The underlying connection was closed: An unexpected error occurred on a send.
---> System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a send.
---> System.IO.IOException: The handshake failed due to an unexpected packet format.
We don't have an in-house TFS admin, otherwise I'd kick this issue over to him. I've tried to use Fiddler to get additional detail, but VS consistently refuses to show up there. I can reach an externally-hosted API while debugging, so I don't think there's a network or proxy problem locking down VS.
Have you tried using TfsTeamProjectCollection class instead of TfsConfigurationServer ?
E.g.
Uri url = new Uri(serverName + rootFolder);
var creds = new NetworkCredential(username, password, Environment.UserDomainName);
var server = new TfsTeamProjectCollection(url, creds);
server.Authenticate();
You can also try debugging this issue using Fiddler. You'll have to change VS proxy settings before starting Fiddler:
Either set the registry key reg add hkcu\SOFTWARE\Microsoft\VisualStudio\12.0\TeamFoundation\RequestSettings
/v BypassProxyOnLocal /t REG_SZ /d False
or
Set environment variable TFS_BYPASS_PROXY_ON_LOCAL=0
Seems like an SSL handshake issue at its root, which has nothing to do with the TFS and HTTP protocol and authentication, they sit above SSL. So make sure you have a valid certificate, matching hostname, good validity, accessible CRL where the cert is not revoked, etc. Also check in other browsers or openssl.exe ("openssl.exe s_client -connect servername:8080") for more diagnostic info. You didn't mention but a proxy or an SSL-level certificate authentication could also cause problems, should be easily debuggable by the methods I mentioned above.
I'm using Amazon .NET SDK, and adding file from my ASP.NET MVC app is working fine from my dev machine, when I`m deploying the app (on AppHarbor) I get the following error:
Could not establish trust relationship for the SSL/TLS secure channel.
Here is the code I`m using:
var config = new Amazon.S3.AmazonS3Config();
config.CommunicationProtocol = Amazon.S3.Model.Protocol.HTTPS;
using (var client = Amazon.AWSClientFactory.CreateAmazonS3Client("key", "secret", config))
{
var putRequest = new Amazon.S3.Model.PutObjectRequest();
putRequest.BucketName = "media.bunkerapp.com";
putRequest.CannedACL = Amazon.S3.Model.S3CannedACL.PublicRead;
putRequest.ContentType = file.ContentType;
putRequest.InputStream = file.InputStream;
putRequest.Key = "mykey";
Amazon.S3.Model.S3Response response = client.PutObject(putRequest);
response.Dispose();
}
I know that EU bucket cannot contains ., as seen on this question but I'm using a US Standard bucket. And again, the issue here is that it's not working on AppHarbor. I tried to roll-back to a 1 instance app, but it throw the same error, here is the stack trace:
at Amazon.S3.AmazonS3Client.ProcessRequestError(String actionName, HttpWebRequest request, WebException we, HttpWebResponse errorResponse, String requestAddr, WebHeaderCollection& respHdrs, Type t)
at Amazon.S3.AmazonS3Client.Invoke[T](S3Request userRequest)
at Amazon.S3.AmazonS3Client.PutObject(PutObjectRequest request)
at MyController...
Any pointer would be greatly appreciated.
I can't reproduce this issue locally or on AppHarbor. I'm using similar code, bucket name (in US) and the newest AWS SDK.
I tried downgrading to version 1.3.4.1 and got an error similar to the one you describe ("The remote certificate is invalid according to the validation procedure").
Upgrading to the newest version of the AWS SDK for .NET (currently 1.4.3.0) may be the solution.