全部產品
Search
文件中心

ApsaraDB RDS:使用SSL鏈路串連RDS PostgreSQL資料庫

更新時間:Jul 09, 2024

本文介紹配置了SSL鏈路加密後,如何通過pgAdmin、psql命令列終端以及JDBC串連資料庫。

前提條件

操作步驟

pgAdmin用戶端SSL串連

pgAdmin用戶端是PostgreSQL官方推薦的資料庫連接工具,在PostgreSQL官方網站下載並安裝PostgreSQL時,將會自動安裝pgAdmin 4用戶端。下文以pgAdmin 4 V6.2.0為例,介紹如何串連RDS PostgreSQL執行個體。

如果您不想安裝PostgreSQL,也可以單獨下載pgAdmin用戶端,僅用於串連遠端資料庫。

  1. 啟動pgAdmin 4用戶端。

    說明

    高版本用戶端首次登入需要設定Master Password用於保護儲存的密碼和其他憑據。

  2. 按右鍵Servers,選擇Register > Server...

  3. General頁簽設定串連名稱。

  4. 選擇Connection標籤頁,輸入要串連的執行個體資訊。 串連資訊

    參數

    說明

    Host name/address

    RDS PostgreSQL執行個體的串連地址及對應的連接埠。

    • 若通過內網串連,需輸入RDS執行個體的內網地址和內網連接埠。

    • 若使用外網串連,需輸入RDS執行個體的外網地址和外網連接埠。

    您可以在RDS PostgreSQL執行個體的資料庫連接頁面查看。

    更多資訊,請參見查看或修改串連地址和連接埠

    Port

    Username

    RDS PostgreSQL執行個體的帳號和密碼。

    建立RDS執行個體的帳號請參見建立帳號和資料庫

    Password

  5. 選擇Parameters標籤頁,添加SSL認證方式相關參數並配置認證。

    參數

    說明

    SSL mode

    PostgreSQL資料庫開啟SSL鏈路加密後,表示允許用戶端通過SSL串連資料庫,在用戶端串連資料庫時,請根據以下情境選擇SSL mode參數的取值。

    • 資料庫未配置用戶端存取控制

      • 通過SSL串連時,SSL mode選擇Require、Verify-CA或Verify-Full。

      • 不通過SSL串連時,SSL mode選擇Disable。

    • 資料庫配置了用戶端存取控制,用戶端必須使用SSL串連,SSL mode選擇Require、Verify-CA或Verify-Full。

    Require、Verify-CA和Verify-Full含義如下:

    • Require:只對資料鏈路加密,並不驗證資料庫的真實性。

    • Verify-CA:加密資料鏈路,同時驗證資料庫的真實性。

    • Verify-Full:加密資料鏈路,驗證資料庫的真實性,同時比對認證內的CN或DNS與串連時配置的資料庫連接地址是否一致。

    Client certificate

    如果完成了配置用戶端CA認證,則需要配置此參數,表示用戶端認證(client.crt)。

    Client certificate key

    如果完成了配置用戶端CA認證,則需要配置此參數,表示用戶端認證私密金鑰(client.key)。

    Root certificate

    SSL mode取值為Verify-CAVerify-Full時,需要配置此參數,表示資料庫CA憑證路徑。

    說明
    • 本樣本中,用戶端認證(client.crt)、用戶端認證私密金鑰(client.key)和資料庫CA認證(server-ca.crt)的檔案路徑請根據實際情況配置。

    • 本樣本以配置自訂認證為例,除自訂認證外,您也可以配置雲端認證,例如將server-ca.crt替換為ApsaraDB-CA-Chain.pem

  6. 單擊Save

    若串連資訊無誤,會出現如下介面,則表示串連成功。

    重要

    postgres是RDS執行個體預設的系統資料庫,請勿在該資料庫中進行任何操作。

psql命令列終端SSL串連

說明

本步驟依賴本地PostgreSQL用戶端內建的psql命令列工具,請確保您已安裝PostgreSQL用戶端,具體請參見PostgreSQL官方文檔

  1. /var/lib/pgsql目錄下建立.postgresql檔案夾。

    mkdir /var/lib/pgsql/.postgresql
  2. 將如下檔案拷貝到.postgresql檔案夾中。

    cp client.crt client.key server-ca.crt /var/lib/pgsql/.postgresql/
    說明
    • 本樣本中,用戶端認證(client.crt)、用戶端認證私密金鑰(client.key)和資料庫CA認證(server-ca.crt)的檔案路徑請根據實際情況配置。

    • 本樣本以配置自訂認證為例,除自訂認證外,您也可以配置雲端認證,例如將server-ca.crt替換為ApsaraDB-CA-Chain.pem

  3. 修改.postgresql檔案夾許可權。

    chown postgres:postgres /var/lib/pgsql/.postgresql/*
    chmod 600 /var/lib/pgsql/.postgresql/*
  4. 使用如下命令編輯postgres使用者的環境變數。

    vim /var/lib/pgsql/.bash_profile
  5. 輸入i進入編輯模式,補充如下內容。

    export PGSSLCERT="/var/lib/pgsql/.postgresql/client.crt"
    export PGSSLKEY="/var/lib/pgsql/.postgresql/client.key"
    export PGSSLROOTCERT="/var/lib/pgsql/.postgresql/ca1.crt"
  6. 使用Esc退出編輯模式,然後輸入:wq儲存並退出。

  7. 重新載入環境變數。

    source .bash_profile
  8. 設定串連時用戶端對資料庫的認證方式。

    export PGSSLMODE="verify-full"

    PostgreSQL資料庫開啟SSL鏈路加密後,表示允許用戶端通過SSL串連資料庫,在用戶端串連資料庫時,請根據以下情境選擇PGSSLMODE參數的取值。

    資料庫是否配置用戶端存取控制

    是否需要通過SSL串連

    PGSSLMODE取值

    require、verify-ca或verify-full

    disable

    必須使用SSL

    require、verify-ca或verify-full

    說明

    require、verify-ca和verify-full含義如下:

    • require:只對資料鏈路加密,並不驗證資料庫的真實性。

    • verify-ca:加密資料鏈路,同時驗證資料庫的真實性。

    • verify-full:加密資料鏈路,驗證資料庫的真實性,同時比對認證內的CN或DNS與串連時配置的資料庫連接地址是否一致。

  9. 串連資料庫。

    psql -h <資料庫連接地址> -U <使用者名稱> -p <連接埠號碼> -d <資料庫名>

    各參數在RDS控制台的擷取位置:

    參數

    擷取方式

    資料庫連接地址

    加密的串連地址,通過SSL頁面中保護主機參數擷取。

    使用者名稱

    通過帳號管理頁面擷取使用者名稱。

    連接埠號碼

    預設5432,如果您修改過,通過資料庫連接頁面擷取。

    資料庫名

    postgres是RDS執行個體預設的系統資料庫,請勿在該資料庫中進行任何操作。如果您需要串連RDS執行個體下建立的其他資料庫,可從資料庫管理頁面擷取。

JDBC SSL串連

  1. 下載如下檔案到本地。

  2. 將用戶端私密金鑰(client.key)轉換為pk8格式。

    openssl pkcs8 -topk8 -inform PEM -in client.key -outform der -out client.pk8 -v1 PBE-MD5-DES
    # 需要輸入密碼,串連時需要使用
    Enter Encryption Password:
    Verifying - Enter Encryption Password:
    警告

    該命令必須在應用程式所在裝置上執行,使用應用程式所在裝置上的openssl命令將私密金鑰轉換為pk8格式,否則可能提示如下報錯:

    • org.postgresql.util.PSQLException: Could not decrypt SSL key file C:/Users/XXX/XXX/client.pk8

    • org.postgresql.util.PSQLException: SSL error: Received fatal alert: unexpected_message

  3. 以Maven專案為例,在pom.xml中匯入PostgreSQL的Maven依賴。

     <dependency>
        <groupId>org.postgresql</groupId>
        <artifactId>postgresql</artifactId>
        <version>42.2.10</version>
      </dependency>
  4. 在業務代碼中編寫JDBC SSL串連PostgreSQL。

    說明

    本樣本以配置自訂認證為例,除自訂認證外,您也可以配置雲端認證,例如將server-ca.crt替換為ApsaraDB-CA-Chain.pem

    public class PgSslDemo {
        public static void main(String[] args) {
            // 設定RDS PostgreSQL執行個體的串連地址
            String hostname = "pgm-bp1gclw58u36s6****.pg.rds.aliyuncs.com";
            // 設定RDS PostgreSQL執行個體的串連連接埠
            String port = "5432";
            // 設定待串連的資料庫名
            String dbname = "postgres";
    
            String jdbcUrl = "jdbc:postgresql://" + hostname + ":" + port + "/" + dbname + "?binaryTransfer=true";
    
            Properties properties = new Properties();
            // 設定串連資料庫的使用者名稱
            properties.setProperty("user", "test_user");
            //設定串連資料庫的密碼
            properties.setProperty("password", "test_pwd");
            // 設定認證存放路徑
            String path = "D:\\ssl\\";
    
            // 配置以SSL訪問
            properties.setProperty("ssl", "true");
            //設定認證授權機構的公開金鑰名
            properties.setProperty("sslrootcert", path + "/" + "server-ca.crt");
            //設定用戶端認證私密金鑰名
            properties.setProperty("sslkey", path + "/" + "client.pk8");
            //設定用戶端認證名
            properties.setProperty("sslcert", path + "/" + "client.crt");
            //填寫將私密金鑰key格式轉換為pk8格式時設定的密碼
            properties.setProperty("sslpassword", "test_ssl_pwd");
    
            // 配置SSL模式,可選值為require、verify-ca、verify-full
            properties.setProperty("sslmode", "verify-ca");
    
            try {
                Class.forName("org.postgresql.Driver");
                Connection connection = DriverManager.getConnection(jdbcUrl, properties);
                //本樣本中,假設在postgres資料庫中存在表example,此處以查詢表example資料為例。
                PreparedStatement preparedStatement = connection.prepareStatement("select * from " +
                        "students01");
                ResultSet resultSet = preparedStatement.executeQuery();
                while (resultSet.next()) {
                    ResultSetMetaData rsmd = resultSet.getMetaData();
                    int columnCount = rsmd.getColumnCount();
                    Map map = new HashMap();
                    for (int i = 0; i < columnCount; i++) {
                        map.put(rsmd.getColumnName(i + 1).toLowerCase(), resultSet.getObject(i + 1));
                    }
                    System.out.println(map);
                }
            } catch (Exception exception) {
                exception.printStackTrace();
            }
        }
    }