Reputation: 37095
I am having trouble connecting to Amazon Keyspaces, both with my application code and cqlsh
:
cqlsh cassandra.eu-west-2.amazonaws.com 9142 -u "xxxxxxxxxxxxxxx" -p "xxxxxxxxxxxxxxxxxxxxxx" --ssl
Connection error: ('Unable to connect to any servers', {'3.10.201.209': error(1, u"Tried connecting to [('3.10.201.209', 9142)]. Last error: [SSL] internal error (_ssl.c:727)")})
What is particularly confusing is that my setup worked in the past.
My cqlshrc
:
[connection]
port = 9142
factory = cqlshlib.ssl.ssl_transport_factory
[ssl]
validate = true
certfile = /home/abc/.cassandra/AmazonRootCA1.pem
I fetched the certificate like this:
wget -c https://www.amazontrust.com/repository/AmazonRootCA1.pem
DNS seems fine:
nslookup cassandra.eu-west-2.amazonaws.com
Server: 8.8.8.8
Address: 8.8.8.8#53
Non-authoritative answer:
Name: cassandra.eu-west-2.amazonaws.com
Address: 3.10.201.209
I recently upgraded to Ubuntu 20.04 from 18.04, which may be causing issues.
Update: Yes, it probably changed the default SSL protocol
Upvotes: 2
Views: 679
Reputation: 325
Based on the answer above, have added one line to the C# sample code provided by AWS:
X509Certificate2Collection certCollection = new X509Certificate2Collection();
X509Certificate2 amazoncert = new X509Certificate2(@"path_to_certificate\sf-class2-root.crt");
var userName = "user_name";
var pwd = "password";
certCollection.Add(amazoncert);
**var sslOptions = new SSLOptions(SslProtocols.Tls12, true, null);**
var awsEndpoint = "cassandra.us-east-2.amazonaws.com";
try
{
var cluster = Cluster.Builder()
.AddContactPoints(awsEndpoint)
.WithPort(9142)
.WithAuthProvider(new PlainTextAuthProvider(userName, pwd))
.WithSSL(sslOptions.SetCertificateCollection(certCollection))
.Build();
var session = cluster.Connect();
var rs = session.Execute("SELECT * FROM tutorialkeyspace.tutorialtable;");
foreach(var row in rs)
{
var name = row.GetValue<String>("keyspace_name");
return name;
}
}
catch(Exception ex)
{
}
Upvotes: 0
Reputation: 37095
I figured it out for cqlsh
; you need to set the SSL version:
[connection]
port = 9142
factory = cqlshlib.ssl.ssl_transport_factory
[cql]
version = 3.4.4
[ssl]
validate = true
certfile = /home/abc/.cassandra/AmazonRootCA1.pem
version = TLSv1_2
The fix for .NET solution is similar; you must set the SslProtocols
correctly.
Here is an F# script that works:
#load "../.paket/load/netcoreapp3.1/CassandraCSharpDriver.fsx"
open System
open System.Net.Security
open System.Security
open System.Security.Authentication
open System.Security.Cryptography
open System.Security.Cryptography.X509Certificates
open Cassandra
let private getEnvVar (name : string) =
let x = Environment.GetEnvironmentVariable name
if String.IsNullOrWhiteSpace x
then
failwithf "The environment variable %s must be set" name
else
x
let region = getEnvVar "AWS_REGION"
let keyspace = getEnvVar "AWS_KEYSPACES_KEYSPACE"
let keyspacesUsername = getEnvVar "AWS_KEYSPACES_USERNAME"
let keyspacesPassword = getEnvVar "AWS_KEYSPACES_PASSWORD"
async {
let certCollection = X509Certificate2Collection ()
use cert = new X509Certificate2 (@"./AmazonRootCA1.pem", "amazon")
certCollection.Add (cert) |> ignore
let sslOptions =
SSLOptions
(
SslProtocols.Tls12,
true,
(fun sender certificate chain sslPolicyErrors ->
if sslPolicyErrors = SslPolicyErrors.None
then
true
else
printfn "Cassandra node SSL certificate validation error(s): {%A}" sslPolicyErrors
false)
)
|> (fun x -> x.SetCertificateCollection(certCollection))
let contactPoints = [| sprintf "cassandra.%s.amazonaws.com" region |]
let cluster =
Cluster.Builder()
.AddContactPoints(contactPoints)
.WithPort(9142)
.WithAuthProvider(PlainTextAuthProvider (keyspacesUsername, keyspacesPassword))
.WithSSL(sslOptions)
.Build()
use! cassandra =
cluster.ConnectAsync keyspace
|> Async.AwaitTask
printfn "Connected. "
}
|> Async.RunSynchronously
It should be easy to translate to C# :)
Upvotes: 4