SSL-соединение с Google Cloud Postgres
Я перенес свою базу данных postgres в Google Cloud SQL.
Без включенного SSL я могу подключиться без проблем.
Однако я изо всех сил пытаюсь заставить работать SSL-соединение.
Я использую драйвер пула pgx.
Я загрузил pem-файлы сервера, клиента и закрытого ключа.
Я получаю сообщение об ошибке
не удалось написать стартовое сообщение (x509: сертификат, подписанный неизвестным органом)
serverCert, err := ioutil.ReadFile("server-ca.pem")
if err != nil {
log.Fatal(err)
}
clientCert, err := ioutil.ReadFile("client-cert.pem")
if err != nil {
log.Fatal(err)
}
caCertPool := x509.NewCertPool()
ok := caCertPool.AppendCertsFromPEM(serverCert)
ok = caCertPool.AppendCertsFromPEM(clientCert)
fmt.Println(ok)
keypair, err := tls.LoadX509KeyPair("server-client-certs.pem", "client-key.pem")
if err != nil {
log.Fatal(err)
}
tlsConfig := &tls.Config{
Certificates: []tls.Certificate{keypair},
ServerName: s.Host,
ClientCAs: caCertPool,
ClientAuth: tls.RequestClientCert,
GetClientCertificate: func(*tls.CertificateRequestInfo) (*tls.Certificate, error) {
return &keypair, nil
},
}
connectionString := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s connect_timeout=%d sslmode=require",
s.Host, s.Port, s.User, s.Password, s.Name, s.ConnectTimeout)
connConfig, err := pgxpool.ParseConfig(connectionString)
if connConfig != nil {
connConfig.ConnConfig.TLSConfig = tlsConfig
}
var pool *pgxpool.Pool
pool, err = pgxpool.ConnectConfig(context.Background(), connConfig)
1 ответ
У вас есть ряд проблем с вашим tls.Config
, Я рекомендую вам прочитать документацию, чтобы понять, что делает каждое поле.
Создание пула CA:
В CertPool
должен содержать сертификат ЦС, используемый для подписи сертификата сервера, это server-ca.pem
. Сертификат клиента не требуется.
Указание пула ЦС:
ClientCAs
- это пул ЦС, используемый сервером для проверки сертификатов клиентов, он используется только на стороне сервера. Вам необходимо указать пул ЦС вRootCAs
.
Это причина вашей проблемы, ваш клиент пытается проверить сертификат сервера, но не знает его CA.
Другие поля:
ClientAuth
- это поле на стороне сервера, используемое для обеспечения определенного поведения сертификата клиента, оно не действует, если установлено на стороне клиента.
GetClientCertificate
не нужен, пока Certificates
установлен, вы можете просто избавиться от него.
Вам также следует дважды проверить свой сертификат клиента. Вы загружаете пару ключейserver-client-certs.pem
/ client-key.pem
. Если это действительно клиентский сертификат и ключ, тогда все будет в порядке.
Предполагая, что вы можете подключиться к узлу базы данных (в белом списке брандмауэра), все ваши сертификаты верны (сертификат CA для сервера, сертификат клиента и ключ клиента), исправления, перечисленные здесь, позволят вам подключиться.
После всего этого ваш код становится:
caCertPool := x509.NewCertPool()
ok := caCertPool.AppendCertsFromPEM(serverCert)
fmt.Println(ok)
keypair, err := tls.LoadX509KeyPair("server-client-certs.pem", "client-key.pem")
if err != nil {
log.Fatal(err)
}
tlsConfig := &tls.Config{
Certificates: []tls.Certificate{keypair},
ServerName: s.Host,
RootCAs: caCertPool,
}
Заключительное примечание: server-ca.pem
не сертификат сервера, это сертификат ЦС, используемый для подписи сертификата сервера. Клиент не будет знать сертификат сервера заранее, он получит его во время рукопожатия TLS.