PostgreSQL sunucusunun SSL sertifikası nasıl incelenir?


14

Çalışan bir PostgreSQL sunucusu olduğunu ve SSL'nin etkin olduğunu varsayalım. "Standart" Linux ve PostgreSQL araçlarını kullanarak SSL sertifikasını nasıl inceleyebilirim?

Koşudan elde edeceğinize benzer çıktılar almayı umuyorum openssl x509 -text .... Ve bir veya iki satırlı komut satırı cevabı bekliyorum, bu yüzden bir paket dinleyicisi çalıştırmak için başvurmak zorunda değilim.

PostgreSQL sunucusuna erişimim yok, bu yüzden yapılandırma dosyalarına doğrudan bakamıyorum.

Bir süper kullanıcı girişi yok, bu yüzden ssl_cert_fileayarın değerini ve ardından alamıyorum pg_read_file.

openssl s_client -connect ...PostgreSQL, SSL anlaşmasını hemen yapmak istemediği için kullanmak işe yaramıyor.

psqlBelgelere hızlıca baktığımda, başlangıçta bu bilgileri göstermesini sağlayan bir komut satırı parametresi bulamadım. (Bana bazı şifre bilgilerini göstermesine rağmen.)

Yanıtlar:


7

Görünüşe göre OpenSSL'nin s_clientaracı 1.1.1'de kullanarak Postgres desteği eklendi -starttls, böylece artık OpenSSL'nin komut satırı araçlarının tüm gücünü ek yardımcı komut dosyaları olmadan kullanabilirsiniz:

openssl s_client -starttls postgres -connect my.postgres.host:5432 # etc...

Referanslar:


10

Craig Ringer'ın yorumundaki fikri takip ederek:

Bir seçenek, openssl s_clientPostgreSQL protokolü ile tokalaşmaktır. PgJDBC'ye özel bir SSLSocketFactory ileterek Java ile de yapabilirsiniz. Basit seçeneklerin olduğundan emin değilim.

... basit bir SSL soket fabrikası yazdım. PgJDBC'nin kendi NonValidatingFactorysınıfının kodunu kopyaladım ve sadece sertifikaları yazdırmak için kod ekledim.

Her şey söylendiğinde ve yapıldığında şöyle görünüyordu:

import java.security.GeneralSecurityException;
import java.security.cert.X509Certificate;
import java.sql.Connection;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.postgresql.ds.PGSimpleDataSource;
import org.postgresql.ssl.WrappedFactory;

public class ShowPostgreSQLCert {
    public static void main(String[] args) throws Throwable {
        PGSimpleDataSource ds = new PGSimpleDataSource();
        ds.setServerName( ... );
        ds.setSsl(true);
        ds.setUser( ... );
        ds.setDatabaseName( ... );
        ds.setPassword( ... );
        ds.setSslfactory(DumperFactory.class.getName());
        try (Connection c = ds.getConnection()) { }
    }

    public static class DumperFactory extends WrappedFactory {
        public DumperFactory(String arg) throws GeneralSecurityException {
            SSLContext ctx = SSLContext.getInstance("TLS");
            ctx.init(null, new TrustManager[] { new DumperTM() }, null);
            _factory = ctx.getSocketFactory();
        }
    }

    public static class DumperTM implements X509TrustManager {
        public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }
        public void checkClientTrusted(X509Certificate[] certs, String authType) { }
        public void checkServerTrusted(X509Certificate[] certs, String authType) {
            for (int i=0; i<certs.length; ++i) {
                System.out.println("Cert " + (i+1) + ":");
                System.out.println("    Subject: " + certs[i].getSubjectX500Principal().getName());
                System.out.println("    Issuer: " + certs[i].getIssuerX500Principal().getName());
            }
        }
    }
}


Çok teşekkürler. PGSimpleDataSource'u kullanmak istemeyenler için. İşte normal JDBC sürücü kurulumunu kullanmak için değişken: String connectionURL = "jdbc:postgresql://server:62013/dbname"; Properties props = new Properties(); props.setProperty("user", "username"); props.setProperty("password", "password"); props.setProperty("ssl", "true"); props.setProperty("sslfactory", DumperFactory.class.getName()); Connection con = null; // Load the Driver class. Class.forName("org.postgresql.Driver"); con = DriverManager.getConnection(connectionURL, props);
Markus

7

Java'yı yüklemek ve derlemekle uğraşmak istemiyorsanız ve zaten python'unuz varsa, şu python komut dosyasını deneyebilirsiniz: https://github.com/thusoy/postgres-mitm/blob/master/postgres_get_server_cert.py

Sertifika tarihlerini kontrol etmek için kullanıyorum:

postgres_get_server_cert.py example.com:5432 | openssl x509 -noout -dates

Veya metin olarak tam sertifika için:

postgres_get_server_cert.py example.com:5432 | openssl x509 -noout -text

1
Yüklemeden kullanmak için: curl https://raw.githubusercontent.com/thusoy/postgres-mitm/master/postgres_get_server_cert.py | python - example.com:5432(ancak bu şekilde yürüttüğünüzden emin olun!)
Yajo

3

csd'nin cevabı beni gerçekten kurtardı. Java'yı bilmeyen veya unutmayan bizler için daha ayrıntılı bir izlenecek yol.

  1. Sunucunuzun java derleyebildiğinden emin olun. "Hangi javac" komutunu deneyin, eğer "... no javac in ..." gibi bir şey çıkarırsa bir JDK yüklemeniz gerekir (JRE çalışmaz, "java" vardır, "javac" değil).

  2. Zaten sahip değilseniz postgresql-jdbc uygulamasını yükleyin. RHEL6 için komut "yum install postgresql-jdbc" dir. Jar dosyalarının nereye kurulduğunu belirleyin. Her versiyon için bir tane olacak. "/Usr/share/java/postgresql-jdbc3.jar" kullandım.

  3. CSD'nin kodunu kopyalayın ve veritabanı bilgilerini ekleyin (diğer cevap) veya bu cevabın sonunda biraz değiştirilmiş versiyonumu kullanın. Tam olarak "ShowPostgreSQLCert.java" adlı bir dosyaya kaydedin. Büyük / küçük harf önemlidir, başka bir şey olarak adlandırın ve derlenmeyecektir.

  4. ShowPostgreSQLCert.java dosyasının bulunduğu dizinde aşağıdaki komutu çalıştırın (gerekirse postgresql-jdbc3.jar dosyasının konumunu değiştirin): "javac -cp /usr/share/java/postgresql-jdbc3.jar ShowPostgreSQLCert.java". Artık aynı dizinde 3 .class dosyanız olmalıdır.

  5. Son olarak, şu komutu çalıştırın: "java -cp.: / Usr / share / java / postgresql-jdbc3.jar ShowPostgreSQLCert". "." "-cp" ifadesinden sonra, .class dosyalarının geçerli dizinine bakması gerektiği anlamına gelir. Sınıf dosyalarının tam yolunu buraya ekleyebilirsiniz, "." Yolunu .jar dosyasının konumu arasında tutmayı unutmayın.

  6. Komutu farklı bir makinede çalıştırmanız gerekiyorsa, aynı jar dosyasının yüklü olması gerekir (postgresql-jdbc3.jar) veya muhtemelen .class dosyalarını derlediğiniz sunucudan kopyalayabilirsiniz. Ardından .class dosyalarını kopyalayın ve yolları değiştirdikten sonra 5. komutu çalıştırın.

Veritabanı bilgilerini komut satırında .class dosyasına derlemek yerine iletebilmeniz için biraz değiştirdim. Sadece herhangi bir argüman olmadan çalıştırın ve hangi argümanları beklediğini gösteren bir mesaj gösterecektir. csd'nin kod + değişiklikleri:

import java.security.GeneralSecurityException;
import java.security.cert.X509Certificate;
import java.sql.Connection;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.postgresql.ds.PGSimpleDataSource;
import org.postgresql.ssl.WrappedFactory;

public class ShowPostgreSQLCert {
    public static void main(String[] args) throws Throwable {
        PGSimpleDataSource ds = new PGSimpleDataSource();
        if( args.length != 4 ) {
            System.out.println("Not enough arguments. Usage: ShowPostgreSQLCert ServerName User DatabaseName Password");
            System.exit(1);
        }
        ds.setServerName( args[0] );
        ds.setSsl(true);
        ds.setUser( args[1] );
        ds.setDatabaseName( args[2] );
        ds.setPassword( args[3] );
        ds.setSslfactory(DumperFactory.class.getName());
        try (Connection c = ds.getConnection()) { }
    }

    public static class DumperFactory extends WrappedFactory {
        public DumperFactory(String arg) throws GeneralSecurityException {
            SSLContext ctx = SSLContext.getInstance("TLS");
            ctx.init(null, new TrustManager[] { new DumperTM() }, null);
            _factory = ctx.getSocketFactory();
        }
    }

    public static class DumperTM implements X509TrustManager {
        public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }
        public void checkClientTrusted(X509Certificate[] certs, String authType) { }
        public void checkServerTrusted(X509Certificate[] certs, String authType) {
            for (int i=0; i<certs.length; ++i) {
                System.out.println("Cert " + (i+1) + ":");
                System.out.println("    Subject: " + certs[i].getSubjectX500Principal().getName());
                System.out.println("    Issuer: " + certs[i].getIssuerX500Principal().getName());
            }
        }
    }
}

1

Https://stackoverflow.com/questions/3313020/write-x509-certificate-into-pem-formatted-string-in-java adresinden sertifikaları PEM olarak çıkarmak için bir kod ekledim ve bir db belirtme gereğini kaldırdım, kullanıcı adı veya şifre (sertifikayı almak için gerekli değildir).

Bunu kullanarak, PostgreSQL'in yeniden başlatılmasının yeni bir sertifikaya geçmek için maalesef gerekli olduğunu doğrulayabildim.

Bir Java geliştiricisi olmama, oluşturma ve çalıştırma adımlarım muhtemelen çok büyük değil, ancak bir postgresql jdbc bulabildiğiniz sürece çalışıyorlar

# locate postgresql | grep jar
/path/to/a/lib/postgresql-9.1-901-1.jdbc4.jar   <-- this one will do
...

Derlemek için:

javac -cp /path/to/a/lib/postgresql-9.1-901-1.jdbc4.jar ./ShowPostgreSQLCert.java

Koşmak:

java -cp /path/to/a/lib/postgresql-9.1-901-1.jdbc4.jar:. ShowPostgreSQLCert 127.0.0.1

Örnek çıktı:

Cert 1:
    Subject: CN=...
    Issuer: CN=...
    Not Before: Fri Oct 21 11:14:06 NZDT 2016
    Not After: Sun Oct 21 11:24:00 NZDT 2018
-----BEGIN CERTIFICATE-----
MIIHEjCCBfqgAwIBAgIUUbiRZjruNAEo2j1QPqBh6GzcNrwwDQYJKoZIhvcNAQEL
...
IcIXcVQxPzVrpIDT5G6jArVt+ERLEWs2V09iMwY7//CQb0ivpVg=
-----END CERTIFICATE-----

Cert 2:
...

Kaynak:

import java.security.GeneralSecurityException;
import java.security.cert.X509Certificate;
import java.sql.Connection;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.postgresql.ds.PGSimpleDataSource;
import org.postgresql.ssl.WrappedFactory;

import javax.xml.bind.DatatypeConverter;
import java.security.cert.X509Certificate;
import java.io.StringWriter;

public class ShowPostgreSQLCert {
    public static void main(String[] args) throws Throwable {
        PGSimpleDataSource ds = new PGSimpleDataSource();
        if( args.length != 1 ) {
            System.out.println("Not enough arguments.");
            System.out.println("Usage: ShowPostgreSQLCert ServerName");
            System.exit(1);
        }
        ds.setServerName( args[0] );
        ds.setSsl(true);
        ds.setUser( "" );
        ds.setDatabaseName( "" );
        ds.setPassword( "" );
        ds.setSslfactory(DumperFactory.class.getName());
        try (Connection c = ds.getConnection()) { }
        catch (org.postgresql.util.PSQLException e) {
            // Don't actually want to login
        }
    }

    public static class DumperFactory extends WrappedFactory {
        public DumperFactory(String arg) throws GeneralSecurityException {
            SSLContext ctx = SSLContext.getInstance("TLS");
            ctx.init(null, new TrustManager[] { new DumperTM() }, null);
            _factory = ctx.getSocketFactory();
        }
    }

    public static String certToString(X509Certificate cert) {
        StringWriter sw = new StringWriter();
        try {
            sw.write("-----BEGIN CERTIFICATE-----\n");
            sw.write(DatatypeConverter.printBase64Binary(cert.getEncoded()).replaceAll("(.{64})", "$1\n"));
            sw.write("\n-----END CERTIFICATE-----\n");
        } catch (java.security.cert.CertificateEncodingException e) {
            e.printStackTrace();
        }
        return sw.toString();
    }

    public static class DumperTM implements X509TrustManager {
        public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }
        public void checkClientTrusted(X509Certificate[] certs, String authType) { }
        public void checkServerTrusted(X509Certificate[] certs, String authType) {
            for (int i=0; i<certs.length; ++i) {

                System.out.println("Cert " + (i+1) + ":");
                System.out.println("    Subject: " + certs[i].getSubjectX500Principal().getName());
                System.out.println("    Issuer: " + certs[i].getIssuerX500Principal().getName());
                System.out.println("    Not Before: " + certs[i].getNotBefore().toString());
                System.out.println("    Not After: " + certs[i].getNotAfter().toString());

                System.out.println(certToString(certs[i]));
            }
        }
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.