PostgreSQLサーバーのSSL証明書を調べる方法


14

実行中のPostgreSQLサーバーがあり、SSLが有効になっているとします。「標準」のLinuxおよびPostgreSQLツールを使用して、そのSSL証明書を調べるにはどうすればよいですか?

私はあなたが実行から得られるものに似た出力を期待していますopenssl x509 -text ...。また、1行または2行のコマンドラインでの回答を期待しているので、パケットスニファーを実行する必要はありません。

PostgreSQLサーバーにアクセスできないため、その構成ファイルを直接見ることができません。

私はスーパーユーザーのログインを持っていないので、ssl_cert_file設定の値を取得できませんpg_read_file

openssl s_client -connect ...PostgreSQLはSSLハンドシェイクをすぐに実行したくないようであるため、使用は機能しません。

psqlドキュメントをざっと見てみると、起動時にその情報を表示するコマンドラインパラメーターが見つかりませんでした。(特定の暗号情報は表示されますが。)

回答:


6

OpenSSLのs_clientツール-starttlsは1.1.1 を使用してPostgresのサポートを追加したように見えるため、追加のヘルパースクリプトなしでOpenSSLのコマンドラインツールの全機能を使用できるようになりました。

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

参照:


10

クレイグリンガーのコメントのアイデアに従ってください。

1つのオプションはopenssl s_client、PostgreSQLプロトコルとのハンドシェイクにパッチを適用することです。また、カスタムSSLSocketFactoryをPgJDBCに渡すことで、Javaでも可能です。単純なオプションがあるかどうかはわかりません。

...単純なSSLソケットファクトリを作成しました。PgJDBC自身のNonValidatingFactoryクラスのコードをコピーし、証明書を印刷するコードを追加しました。

それがすべて言われ、行われたとき、それは次のように見えました:

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());
            }
        }
    }
}

あなたが揺れます。これをinstall-certに追加しましたgithub.com/spyhunter99/installcert
spy

本当にありがとう。PGSimpleDataSourceを使用したくない人向け。ここで、通常のJDBCドライバーセットアップを使用するためのバリアント: 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のインストールとコンパイルに煩わされたくなくて、すでにpythonがある場合は、次のpythonスクリプトを試すことができます:https : //github.com/thusoy/postgres-mitm/blob/master/postgres_get_server_cert.py

私はそれを使用して証明書の日付を確認します:

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

または、テキストとしての完全な証明書の場合:

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

1
インストールせずに使用するには:(curl https://raw.githubusercontent.com/thusoy/postgres-mitm/master/postgres_get_server_cert.py | python - example.com:5432ただし、この方法で実行することを確認してください!!)
Yajo

3

csdの答えは本当に助かりました。Javaを知らない、または忘れた人のためのより詳細なチュートリアルを以下に示します。

  1. サーバーがJavaをコンパイルできることを確認してください。コマンド "which javac"を試してください。 "... no javac in ..."のようなものが出力される場合は、JDKをインストールする必要があります(JREは機能しません。 "javac"ではなく "java"があります)。

  2. postgresql-jdbcをまだインストールしていない場合はインストールします。RHEL6の場合、コマンドは「yum install postgresql-jdbc」です。jarファイルがインストールされている場所を把握します。バージョンごとに1つずつ、それらのいくつかがあります。「/usr/share/java/postgresql-jdbc3.jar」を使用しました。

  3. csdのコードをコピーしてデータベース情報(他の回答)を挿入するか、この回答の最後に少し修正したバージョンを使用します。「ShowPostgreSQLCert.java」というファイルに保存します。大文字/小文字は重要で、他の名前を付けてコンパイルしません。

  4. ShowPostgreSQLCert.javaファイルがあるディレクトリで、次のコマンドを実行します(必要に応じてpostgresql-jdbc3.jarの場所を変更します):「javac -cp /usr/share/java/postgresql-jdbc3.jar ShowPostgreSQLCert.java」。同じディレクトリに3つの.classファイルがあるはずです。

  5. 最後に、コマンド「java -cp。:/ usr / share / java / postgresql-jdbc3.jar ShowPostgreSQLCert」を実行します。「。」「-cp」の後は、現在のディレクトリで.classファイルを探す必要があることを意味します。ここにクラスファイルへのフルパスを挿入できます。パスと.jarファイルの場所の間に「:」を忘れないでください。

  6. 別のマシンでコマンドを実行する必要がある場合は、同じjarファイル(postgresql-jdbc3.jar)をインストールする必要があります。または、おそらく.classファイルをコンパイルしたサーバーからコピーすることもできます。次に、.classファイルをコピーして、パスを変更した後、5からコマンドを実行します。

.classファイルにコンパイルする代わりにコマンドラインでデータベース情報を渡すことができるように、コードを少し変更しました。引数なしで実行するだけで、期待される引数を示すメッセージが表示されます。csdのコード+変更点:

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

私はからいくつかのコードを追加しました /programming/3313020/write-x509-certificate-into-pem-formatted-string-in-javaからて証明書をPEMとして出力し、dbを指定する必要性を削除しました。ユーザー名またはパスワード(証明書を取得するために必要ありません)。

これを使用して、新しい証明書に切り替えるには、残念ながらPostgreSQLの再起動が必要と思われることを確認できました。

Java開発者ではないので、ビルドして実行するための私の手順はおそらくそれほど素晴らしいものではありませんが、postgresql jdbcを見つけられる限り機能します

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

コンパイルします:

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

走る:

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

サンプル出力:

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:
...

ソース:

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]));
            }
        }
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.