Невозможно подключиться к базе данных AWS с помощью TLS с проверкой ЦС сервера

В документации AWS указано, что для подключения к моему кластеру DocumentDB мне нужно использовать строку запроса, которая заканчивается так ?ssl_ca_certs=rds-combined-ca-bundle.pem&replicaSet=rs0. Это цепочка корневых сертификатов, которую мой Клиент должен подтвердить. Мне не нужен сертификат клиента.

Используя драйвер MongoDB C # и этот конкретный запрос с файлом .pem в том же каталоге, я не могу установить соединение. Если я использую тот же файл .pem и строку запроса из Mongo Shell, я могу правильно подключиться к своей базе данных. Это не работает только с моим основным приложением .net, которое также работает на AWS.

Удалив TLS из кластера и убрав параметр ssl_ca_certs из запроса, я могу правильно подключиться к своему кластеру.

Я думал, что смогу преобразовать свой .pem файл в .pfx, используя openssl, но я должен дать .pfx пароль и В документации MongoDB говорится, что

Крайне важно, чтобы при загрузке сертификата с паролем свойство PrivateKey не было нулевым. Если свойство имеет значение null, это означает, что ваш сертификат не содержит закрытого ключа и не будет передан на сервер.

Как я могу использовать файл .pem, предоставленный Amazon AWS для подключения к моей базе данных с помощью драйвера C # MongoDB?


person David Gourde    schedule 22.02.2019    source источник
comment
Если вы уже используете AWS, вы можете опустить свой сертификат, потому что это внутренний вызов, не так ли?   -  person Nikolaus    schedule 23.02.2019
comment
?ssl_ca_certs=/local/path/to/rds-combined-ca-bundle.pem возможно? В чем ошибка, когда не удается подключиться?   -  person Michael - sqlbot    schedule 23.02.2019
comment
@Nikolaus Нет, удаление ".pem" из строки запроса не помогает.   -  person David Gourde    schedule 24.02.2019
comment
@ Michael-sqlbot Я получаю сообщение TimeOut, не могу найти сервер. Если я удаляю TLS, он работает, поэтому база данных «достижима», но не может быть найдена без проверки сертификата сервера. То же самое и с оболочкой монго. Без добавления сертификата вызов будет TimeOut, и добавление его правильно подключится к базе данных.   -  person David Gourde    schedule 24.02.2019


Ответы (6)


Попробуйте добавить файл CA RDS в хранилище доверенных сертификатов C #.

            X509Store store = new X509Store(StoreName.Root);
            X509Certificate2 ca = new X509Certificate2(<path_to_rds-combined-ca-bundle.pem>);
            try {
                store.Open(OpenFlags.ReadWrite);
                store.Add(ca);
            } catch (Exception ex) {
                Console.WriteLine("Root certificate import failed: " + ex.Message);
                throw;
            } finally {
                store.Close();
            }
person Kanishka Chaturvedi    schedule 25.02.2019
comment
Спасибо, попробую на этой неделе. Но есть ли причина, по которой мне нужно отправлять Client сертификаты, если они мне технически не нужны, а нужно только проверить сертификаты сервера (ssl_ca_certs)? - person David Gourde; 25.02.2019
comment
Отредактировал ответ. Старая ссылка была для TLS на стороне клиента. Достаточно просто добавить сертификат ЦС RDS в хранилище доверенных сертификатов. - person Kanishka Chaturvedi; 25.02.2019

### Подключение к БД документов с помощью простой консоли .Net Приложение с SSL.

-> Прежде всего, включите SSL в кластере БД документов, установив для параметра tls значение «включено». Обязательно перезагрузите узел записи вашего кластера, чтобы перезагрузить весь кластер, чтобы применить изменения группы параметров. По умолчанию TLS включен, когда вы запускаете новый кластер Doc DB.

-> Настройте сертификат SSL в своей среде:

1) Загрузите SSL-сертификат PKCS # 7 на исходный компьютер с Windows по ссылке ниже:

https://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.p7b

2) Щелкните меню "Пуск", выберите "Выполнить" и введите mmc.

3) В MMC, File-> Add / Remove Snap-in.

4) Выберите «Сертификаты» из списка надстроек и нажмите «Добавить».

5) Сертификаты доверенных центров сертификации должны находиться в хранилище локального компьютера, поэтому выберите переключатель «Учетная запись компьютера», нажмите «Далее» и затем выберите «Локальный компьютер». Щелкните Далее, а затем Готово.

6) Теперь на левой панели (в разделе «Корень консоли» вы увидите параметр «Сертификаты». Щелкните по нему.

7) Появится список, щелкните правой кнопкой мыши «Trusted Root Certification Authorities», затем выберите All Tasks-> Import.

8) В открывшемся окне нажмите «Далее», найдите файл сертификата (.p7b), загруженный на шаге 1 (если вы не можете его найти, в раскрывающемся списке «Тип файла» выберите «Все файлы»), а затем «Продолжить». нажмите «Далее» и, наконец, «Готово». Затем сохраните конфигурацию.

-> Затем написал следующий код:

---------------------------------------------------

using MongoDB.Bson;
using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
namespace FirstDocDB
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var connectionString = "mongodb://pulkit:password@ClusterID:27017/?ssl=true&sslVerifyCertificate=true&replicaSet=rs0";
            var client = new MongoClient(connectionString);
            var database = client.GetDatabase("test");
            var collection = database.GetCollection("stuff");
            var document = collection.Find(new BsonDocument()).FirstOrDefault();
            Console.WriteLine(document.ToString());
        }
    }
}

---------------------------------------------------

-> И после сборки и запуска мне удалось получить документ из коллекции с именем «stuff» в качестве вывода: {"_id": ObjectId ("5c5a63b10cf861158c1d241c"), "hello": "world"}

Таким образом, после выполнения вышеуказанных шагов я смог успешно подключиться к базе данных документов с помощью драйвера Mongo для .Net.

person Pulkit Agarwal    schedule 06.03.2019

У меня была аналогичная проблема, был открыт билет с AWS, и она была решена с помощью тех же шагов, что и ответ Pulkit Agarwal.

Основным изменением была строка подключения, даже после добавления сертификата в локальное хранилище я по-прежнему использовал строку запроса как «? Ssl_ca_certs = rds-comb-ca-bundle.pem & replicaSet = rs0», которую нужно изменить на «? Ssl = true & sslVerifyCertificate = true & replicaSet. = rs0 "

person Kathirk    schedule 08.03.2019

Вот примеры того, как программно подключиться к Amazon DocumentDB с помощью C # (и других драйверов) с включенным / отключенным TLS.

https://docs.aws.amazon.com/documentdb/latest/developerguide/connect.html

person Joseph Idziorek    schedule 26.04.2019

Вот еще один способ. Однако я обнаружил, что при использовании SSL с драйвером C # Mongo не выполняется объединение соединений и открывал новое соединение для каждого вызова. Вы можете уменьшить количество активных подключений, включив MaxConnectionIdleTime, но это все еще не идеально, если ваше приложение создает много подключений.

    var connectionString = "username:password@cluster_endpoint:27017/?replicaSet=rs0";
    var clientSettings = MongoClientSettings.FromUrl(new MongoUrl("mongodb://" + connectionString));
    var certificatePath = "ssl\rds-combined-ca-bundle.pem";

    var pem = System.IO.File.ReadAllText(AppDomain.CurrentDomain.BaseDirectory + certificatePath);
    byte[] certBuffer = GetBytesFromPEM(pem, "CERTIFICATE");

    clientSettings.UseSsl = true;
    clientSettings.SslSettings = new SslSettings()
    {
        ClientCertificates = new List<X509Certificate2>()
        {
            new X509Certificate2(certBuffer)
        },
        EnabledSslProtocols = System.Security.Authentication.SslProtocols.Default,
        CheckCertificateRevocation = true
        };

    clientSettings.VerifySslCertificate = true;

    clientSettings.SslSettings.ClientCertificateSelectionCallback = (sender, host, certificates, certificate, issuers) => clientSettings.SslSettings.ClientCertificates.ToList()[0];
    clientSettings.SslSettings.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true;

    clientSettings.MaxConnectionIdleTime = new TimeSpan(0, 0, 30);

    _client = new MongoClient(clientSettings);
    _database = _client.GetDatabase(db.ToString());

person Kenny Dickie    schedule 09.03.2019

Стоит добавить, что в настоящее время драйвер MongoDB C # не поддерживает PEM сертификаты. Таким образом, все, что ссылается на сертификат PEM, не удастся с System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.

Руководство разработчика AWS предлагает вместо этого использовать P7B сертификаты, которые можно загрузить отсюда: https://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.p7b

Это сработало для нас.

В Kubernetes и Windows нам нужно было добавить rds-combined-ca-bundlee.p7b в локальное хранилище доверенных сертификатов, как показано в Пример AWS C # и НЕ ссылайтесь на него в строке подключения.

На Mac у меня возникли проблемы с программным добавлением сертификата P7B в хранилище ключей из-за проблемы access denied. Обновлю ответ, если мне удастся его решить.


Последнее, что стоит упомянуть, ответ, предоставленный Кенни Дики, по существу отключает проверку сертификата и делает установку небезопасной. Эта строка кода clientSettings.SslSettings.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true; всегда будет возвращать true.

person kaminzo    schedule 20.10.2020