分享到

引言

使用 PostgreSQL 資料庫時,您首先需要考慮的事情之一是如何連線和與資料庫例項互動。這需要資料庫客戶端(您用於與資料庫互動的元件)和資料庫伺服器(儲存、組織和提供資料訪問的實際 PostgreSQL 例項)之間的協調。

要成功管理此過程,您需要了解如何配置 PostgreSQL 例項以允許所需的訪問型別和身份驗證方法。在本指南中,我們將介紹如何修改資料庫伺服器的身份驗證機制以滿足您的環境要求。

在配套指南中,我們介紹了如何使用資料庫客戶端連線到 PostgreSQL 例項。建議閱讀這兩份指南,以便更全面地瞭解 PostgreSQL 中的身份驗證工作原理。

瞭解 PostgreSQL 的身份驗證檔案

如果您想修改決定使用者如何向 PostgreSQL 例項進行身份驗證的規則,可以透過修改伺服器配置來實現。

您需要修改的特定檔名為 pg_hba.conf

請注意,您必須重啟 PostgreSQL 例項,任何新的身份驗證配置才能生效。不同的作業系統將以不同的方式處理此問題。在大多數 Linux 發行版中,您可以鍵入 sudo systemctl restart postgresql。如果您透過 brew 安裝了 PostgreSQL,可以嘗試鍵入 brew services restart postgresql。另一種可能適用於更廣泛系統的方法是 pg_ctl restart

查詢 pg_hba.conf 檔案

要查詢伺服器上的 pg_hba.conf 檔案,您可以檢視 PostgreSQL 配置目錄。具體位置將取決於您使用的作業系統和 PostgreSQL 版本。

如果您不知道身份驗證配置檔案的位置,但可以訪問資料庫,則可以查詢 PostgreSQL 以獲取檔案位置,正如 Craig Ringer 在此帖子中演示的那樣

如果您在命令列上,可以鍵入以下內容,它會查詢 pg_hba.conf 檔案的位置,並告訴 PostgreSQL 只打印檔案位置而不進行格式化

psql -t -P format=unaligned -c 'SHOW hba_file;'
/etc/postgresql/10/main/pg_hba.conf

如果您已經打開了一個 PostgreSQL 會話,您可以直接鍵入

SHOW hba_file;
hba_file
-------------------------------------
/etc/postgresql/10/main/pg_hba.conf
(1 row)

一旦您獲得了 pg_hba.conf 檔案的位置,請在您的文字編輯器中開啟它以檢視配置並進行更改

vim /etc/postgresql/10/main/pg_hba.conf

預設情況下,該檔案包含當前配置以及許多有用的註釋。

瞭解 pg_hba.conf 檔案格式

pg_hba.conf 檔案使用純文字實現的表格狀結構。刪除空行和註釋後,一個基本檔案可能看起來像這樣

# TYPE DATABASE USER ADDRESS METHOD OPTIONS
local all postgres peer
local all all peer
host all all 127.0.0.1/32 md5
host all all ::1/128 md5
local replication all peer
host replication all 127.0.0.1/32 md5
host replication all ::1/128 md5

讓我們看看不同欄位的含義以及檔案內容的解釋方式。

pg_hba.conf 檔案的結構和解釋方式

pg_hba.conf 檔案中的每一行都描述了客戶端向系統進行身份驗證的一種方式。每行的大部分內容描述了用於與傳入連線請求進行比較的匹配條件。最終元件指定允許的身份驗證方法和身份驗證所需的任何選項。

當 PostgreSQL 根據身份驗證規則評估連線請求時,它會按順序從上到下進行。如果某行中的配置與連線請求的特徵匹配,PostgreSQL 將使用該行中指定的身份驗證資訊來決定是否對客戶端進行身份驗證。

如果客戶端成功透過身份驗證,將建立連線。如果身份驗證失敗,連線將被拒絕。PostgreSQL *不會* 繼續處理以檢視其他規則是否與請求匹配。因此,您的規則順序很重要。

每行中,欄位由空格(空格或製表符)分隔。儘管將這些欄位格式化成列通常在視覺上很有幫助,但 PostgreSQL 並不要求這樣做。

pg_hba.conf 檔案中每個欄位的含義

現在您對檔案的結構和解釋方式有了一些瞭解,我們可以開始討論每個欄位的含義。

我們將介紹的欄位是

  • 連線型別
  • 資料庫
  • 使用者名稱
  • 地址
  • 身份驗證方法
  • 身份驗證方法的選項

連線型別

每個記錄中的第一個欄位指定要匹配的連線請求型別。只有使用指定連線的請求才能匹配每個規則。

連線型別必須是以下之一:

  • local:具有 local 的記錄匹配透過本地 Unix 域套接字檔案(而不是透過網路)建立的連線。出於安全和效能原因,如果可能,首選本地連線。
  • host:以 host 開頭的行匹配透過網路發出的任何連線請求。這是網路連線的通用捕獲。使用以下型別可以進行更精細的匹配。
  • hostsslhostssl 連線型別匹配透過 TLS/SSL 加密在網路上建立的任何連線。這通常是在允許外部連線時使用的最佳連線型別。
  • hostnosslhostnossl 型別匹配所有未透過 TLS/SSL 加密的網路連線。

從 PostgreSQL 12 開始,還增加了對GSSAPI 連線的支援,引入了這些附加選項

  • hostgssenchostgssenc 連線型別匹配使用 GSSAPI 加密的任何網路連線。此選項僅對那些已經使用 GSSAPI 進行安全保護的使用者有意義。
  • hostnogssenchostnogssenc 型別匹配所有不使用 GSSAPI 加密的網路連線。

資料庫

下一個欄位指定請求嘗試訪問的資料庫。連線請求中指定的資料庫必須滿足此列中的值才能匹配該行。

值可以是以下任意一個:

  • all:資料庫值為 all 是一個全匹配值,它匹配任何請求的資料庫。如果您不希望當前匹配規則評估資料庫值,這會很有用。
  • sameusersameuser 值匹配請求的資料庫和使用者名稱相同的連線。
  • samerole:如果指定的使用者是與請求的資料庫同名的*角色*的成員,則samerole 資料庫值將匹配該連線。
  • replication:使用 replication 值將匹配用於資料庫複製的任何傳入連線。用於複製的連線不提供資料庫目標,因此這會匹配複製請求。
  • [特定資料庫名稱]:您還可以提供一個或多個要匹配的特定資料庫名稱。只有當連線請求列出的資料庫之一時,它們才會匹配。您可以用逗號分隔多個數據庫名稱,或者透過在檔名前加上 @ 符號來指定要從中讀取名稱的檔案。

使用者

下一個欄位用於與連線請求提供的使用者進行匹配。連線的使用者值必須滿足規則的使用者欄位才能匹配該規則。

使用者欄位可以接受以下選項:

  • all:值為 all 告訴 PostgreSQL,連線的使用者引數中的任何值都滿足此規則的使用者要求。
  • [特定使用者或組名]:使用者欄位的唯一其他選項是提供特定使用者、使用者列表或組。多個使用者可以透過逗號分隔值來指定。如果名稱以 + 符號開頭,則將其解釋為組名而不是使用者名稱。在這種情況下,如果請求的使用者是規則指定的組的成員,則規則將匹配。同樣,您可以透過在檔名前加上 @ 符號來告訴 PostgreSQL 從檔案而不是內聯提供值。

地址

對於所有以 host 開頭的連線型別(hosthostsslhostnossl,以及 PostgreSQL 12 及更高版本中的 hostgssenchostnogssenc),接下來是地址欄位。對於 local 連線,此欄位將被跳過。

地址欄位指定客戶端機器的地址或模式,用於與連線的地址進行匹配。這意味著連線將根據其源進行評估。連線的源必須滿足規則的地址值,規則才能匹配。

地址欄位可以填寫以下任何內容:

  • all:地址值為 all 告訴 PostgreSQL 任何客戶端地址都將滿足此條件。
  • samehost:值 samehost 用於表示任何源自伺服器自身 IP 地址的網路連線都應匹配。
  • samenetsamenet 值表示來自伺服器網路子網的任何 IP 地址都將匹配。
  • [CIDR IP 地址範圍]:您還可以使用 CIDR 表示法提供 IP 地址範圍。這可以指定單個 IP 地址(IPv4 地址使用 /32 子網,IPv6 地址使用 /128 子網)或透過提供更廣闊的 CIDR 掩碼來指定地址範圍。IP 地址範圍僅匹配來自指定範圍內的客戶端連線,並使用指定的 IP 協議。
  • [主機名]:也可以直接指定主機名。在這種情況下,客戶端的主機名將透過正向和反向 DNS 查詢進行評估,以確保其解析符合預期。如果指定的主機名以點開頭,則在該域上正確解析的任何主機都將滿足要求。

身份驗證方法

如果連線滿足所有先前的匹配條件,則應用給定的身份驗證方法。這是每行的下一個欄位。

身份驗證方法是 PostgreSQL 決定是否接受符合規則的連線的方式。它可以設定為以下任何選項:

  • trust:值為 trust 會立即接受連線,無需進一步要求。這假定已存在其他外部身份驗證方法。在大多數情況下不推薦使用。
  • reject:值為 reject 會立即拒絕連線。這主要用於過濾掉與不需要的模式匹配的連線。
  • scram-sha-256scram-sha-256 方法將使用 SCRAM-SHA-256 身份驗證檢查使用者提供的密碼。如果所有客戶端都支援它,這目前是密碼身份驗證最安全的選項。
  • md5md5 方法也檢查使用者密碼。此方法不如 scram-sha-256 安全,但支援更廣泛。如果密碼使用 SCRAM 加密,當前實現將自動使用 scram-sha-256,即使指定了 md5
  • passwordpassword 方法是最不安全的密碼身份驗證方法。它以純文字傳送密碼,除非連線使用 TLS/SSL 加密整個連線,否則不應使用。
  • gssgss 方法使用 GSSAPI 進行身份驗證。這可用於身份驗證,無論連線是否使用 GSSAPI 加密。這允許透過 Kerberos 和類似軟體進行身份驗證。
  • sspisspi 方法使用僅限 Windows 的安全支援提供程式介面 API 對客戶端進行身份驗證。
  • identident 方法會向客戶端的 ident 伺服器檢查發起連線的使用者。由於這依賴於客戶端機器,因此只能用於客戶端機器受到嚴格控制的可信網路。
  • peerpeer 身份驗證方法用於本地連線。它向本地作業系統詢問客戶端的系統使用者名稱。它檢查該名稱是否與請求的資料庫名稱匹配。
  • ldapldap 方法透過使用 LDAP 伺服器來驗證使用者名稱和密碼進行身份驗證。
  • radius:選擇 radius 以使用 RADIUS 伺服器檢查使用者名稱和密碼組合。
  • certcert 方法使用 TLS/SSL 客戶端證書對客戶端進行身份驗證。這僅適用於 TLS/SSL 連線。客戶端證書必須是有效且受信任的證書才能被接受。
  • pampam 選項會將身份驗證延遲到作業系統的 PAM 服務
  • bsdbsd 方法使用 BSD 身份驗證服務來驗證使用者名稱和密碼。此方法僅適用於 OpenBSD 主機。

上述某些方法僅適用於某些型別的連線或需要額外基礎設施的情況下。對於大多數部署,rejectpeer 以及 scram-sha-256md5 足以開始,具體取決於您的基礎設施,還可以使用其他方法,如 ldap

身份驗證選項

在身份驗證方法之後,可能存在一個可選的最終列,用於為身份驗證方法提供附加選項。此列的使用很大程度上取決於所選的身份驗證方法型別。

對於引用外部伺服器的身份驗證方法,這些選項通常指定主機和連線資訊,以便 PostgreSQL 可以成功查詢身份驗證服務。另一個常見於許多身份驗證方法的選項是 map 引數,它允許您在系統使用者名稱和 PostgreSQL 資料庫使用者名稱之間進行轉換。

每種身份驗證方法都有自己的一套有效選項。請務必檢視 PostgreSQL 文件中每種方法頁面上適用的選項。

配置常見身份驗證策略

我們已經介紹了一些主要的身份驗證選項,但是如何使用它們來實現合理的策略呢?在本節中,我們將介紹如何配置一些最常見的身份驗證策略。

允許本地使用者連線到匹配的資料庫

通常將 PostgreSQL 配置為允許同一機器上的使用者向匹配的 PostgreSQL 使用者名稱進行身份驗證。例如,使用 peer 身份驗證,如果 PostgreSQL 也有一個名為 john 的使用者名稱,則名為 john 的作業系統使用者將能夠無需密碼自動登入。

這將適用於使用 PostgreSQL 套接字檔案進行的任何本地連線。如果您指定任何網路地址,即使它是 127.0.0.1 本地環回裝置,連線也不會使用套接字,並且不會匹配 peer 身份驗證行。但是,對 localhost 的連線將使用套接字檔案並匹配這些行。

要允許所有 PostgreSQL 使用者透過匹配的作業系統使用者進行身份驗證,請新增一行,匹配 local 連線型別,允許所有資料庫和使用者名稱,並使用 peer 身份驗證

# TYPE DATABASE USER ADDRESS METHOD OPTIONS
local all all peer

如果您想限制此功能,以便只有 johnsue PostgreSQL 使用者可以透過這種方式進行身份驗證,請限制 USER 列的範圍

# TYPE DATABASE USER ADDRESS METHOD OPTIONS
local all john,sue peer

如果您需要允許名為 sue 的作業系統使用者對名為 susan 的資料庫使用者進行身份驗證,您可以在行末尾指定一個 map 選項。選擇一個對映名稱來標識此對映

# TYPE DATABASE USER ADDRESS METHOD OPTIONS
local all john,sue peer map=my-map-name

然後,您可以透過在同一目錄中開啟 pg_ident.conf 檔案來對映您的使用者

vim pg_ident.conf

透過在此檔案中新增一行,指定您選擇的對映名稱、作業系統使用者名稱和 PostgreSQL 使用者名稱(用空格分隔),來建立所需的對映

# MAPNAME SYSTEM-USERNAME PG-USERNAME
my-map-name sue susan

現在,作業系統使用者 sue 將能夠像匹配一樣透過 peer 身份驗證對 PostgreSQL 使用者 susan 進行身份驗證。

允許來自同一機器的網路連線使用密碼

要使用密碼對來自 PostgreSQL 伺服器機器的網路連線(非套接字連線)進行身份驗證,您需要匹配 host 連線型別而不是 local。然後,您可以將可接受的地址限制為本地環回裝置,並允許使用者使用 md5scram-sha-256 進行身份驗證。

例如,如果 PostgreSQL 託管機器上的使用者嘗試透過將 127.0.0.1 指定為主機來連線,PostgreSQL 可以執行密碼身份驗證。

要設定此功能,我們需要使用 host 連線型別。接下來,我們需要指定可接受的地址範圍。由於此規則應僅匹配本地連線,因此我們將指定本地環回裝置。我們將不得不新增兩行單獨的行來匹配 IPv4 和 IPv6 環回裝置。

之後,您可以指定要用於身份驗證的密碼方案。scram-sha-256 方法更安全,但 md5 方法支援更廣泛。

最終的身份驗證行將如下所示

# TYPE DATABASE USER ADDRESS METHOD OPTIONS
host all all 127.0.0.1/32 md5
host all all ::1/128 md5

您可以透過將相應的列從 all 更改為逗號分隔的特定實體列表,來限制允許使用此方法進行身份驗證的資料庫或使用者。

允許自動維護

定期執行各種自動維護任務。為確保這些操作能夠正常進行身份驗證和執行,您需要確保管理帳戶能夠非互動式地進行身份驗證。

預設情況下,postgres 帳戶配置為此角色,使用 peer 身份驗證。此行很可能已經存在於您的 pg_hba.conf 檔案中

# TYPE DATABASE USER ADDRESS METHOD OPTIONS
local all postgres peer

請確保此檔案或類似行存在於您的檔案中,特別是如果您正在更改許多其他身份驗證方法。

允許用於複製的連線

複製是一種特殊的程序,它將資料從一個數據庫複製到另一個數據庫,通常是頻繁進行。與其他型別的連線不同,複製連線不指定它們要連線的特定資料庫。

資料庫列中的 replication 關鍵字用於匹配這些複製連線。任何具有 replication 許可權的使用者都能夠建立複製連線。

為了允許所有本地複製連線,並以與我們之前針對常規連線(Unix 套接字上的 peer 和本地網路上的 md5)相同的方式進行映象,我們可以新增以下行

# TYPE DATABASE USER ADDRESS METHOD OPTIONS
local replication all peer
host replication all 127.0.0.1/32 md5
host replication all ::1/128 md5

要允許從其他位置進行復制,您可以新增其他地址。例如,要允許從本地 192.0.2.0/24 網路上的任何機器進行復制,您可以新增如下一行

# TYPE DATABASE USER ADDRESS METHOD OPTIONS
host replication all 192.0.2.0/24 md5

這將允許來自該網路內的任何機器的複製連線使用 md5 加密的密碼進行身份驗證。

允許來自本地網路的連線使用密碼

上面,我們演示瞭如何為本地複製連線配置密碼身份驗證。這可以推廣到允許任何本地網路連線的密碼身份驗證。

要允許來自本地 192.0.2.0/24 網路的任何連線使用 md5 密碼進行身份驗證,您可以新增如下一行

# TYPE DATABASE USER ADDRESS METHOD OPTIONS
host all all 192.0.2.0/24 md5

這將允許 192.0.2.0/24 網路中的所有主機透過網路使用 md5 加密的密碼對 PostgreSQL 進行身份驗證。

允許使用 SSL 和密碼的遠端連線

要允許來自受信任網路之外的連線,您應該始終透過安全加密(如 TLS/SSL)來隧道化連線。如果您需要允許這些連線,您應該匹配 hostssl 連線型別。

例如,要允許從任何可以連線到資料庫伺服器的地方進行密碼身份驗證,但僅限於使用 TLS/SSL 的情況,您可以在身份驗證檔案中新增如下一行

# TYPE DATABASE USER ADDRESS METHOD OPTIONS
hostssl all all all md5

這將允許任何使用 TLS/SSL 的外部連線使用 md5 加密的密碼進行身份驗證。您可以透過指定更嚴格的地址輕鬆限制訪問。

如果您使用 hostssl 連線型別,則必須為 PostgreSQL 例項配置 SSL。您將必須生成或以其他方式獲取 SSL 證書、SSL 金鑰和 SSL 根證書,然後修改 postgresql.conf 配置檔案,如 PostgreSQL SSL 配置文件中所述。

允許使用 SSL 和 SSL 客戶端證書的遠端連線

如果您已經強制對外部連線使用 SSL,您可能需要考慮使用 SSL 客戶端證書進行身份驗證,而不是密碼。這將允許客戶端出示其客戶端 SSL 證書。伺服器會檢查其是否有效並由受信任的證書頒發機構簽名。如果有效,它將根據提供的規則允許身份驗證。

要設定 SSL 客戶端身份驗證,我們可以使用與之前類似的行

# TYPE DATABASE USER ADDRESS METHOD OPTIONS
hostssl all all all cert

透過此配置,伺服器將不會提示使用者輸入密碼,而是要求提供有效的 SSL 證書。證書的通用名稱 (CN) 欄位必須與所請求的資料庫使用者匹配,或者透過 map 檔案進行配置。

例如,對於 CN 為 katherine 的證書,要對名為 kate 的 PostgreSQL 使用者進行身份驗證,您需要在 pg_hba.conf 檔案中指定一個對映檔案

# TYPE DATABASE USER ADDRESS METHOD OPTIONS
hostssl all all all cert map=my-map-name

之後,您將編輯 pg_ident.conf 檔案,以明確地將這兩個使用者對映在一起

vim pg_ident.conf
# MAPNAME SYSTEM-USERNAME PG-USERNAME
my-map-name katherine kate

您可以學習如何在 PostgreSQL 的 TLS/SSL 客戶端證書文件中建立和配置客戶端證書。

結論

在本指南中,我們從伺服器端介紹了 PostgreSQL 身份驗證。我們演示瞭如何修改 PostgreSQL 例項的配置以更改允許客戶端進行身份驗證的方式。在討論了身份驗證檔案中可用的不同選項之後,我們介紹瞭如何使用之前學到的知識實現一些常見的身份驗證策略。

瞭解如何配置身份驗證,結合對如何與 PostgreSQL 客戶端連線的理解,可以幫助您授予合法客戶端訪問許可權,同時防止不必要的連線。此配置是保護資料庫例項並防止可能阻礙操作的破壞性登入問題的重要組成部分。

關於作者
Justin Ellingwood

Justin Ellingwood

Justin 自 2013 年以來一直撰寫關於資料庫、Linux、基礎設施和開發者工具的文章。他目前與妻子和兩隻兔子住在柏林。他通常不必用第三人稱寫作,這讓所有相關方都感到欣慰。
© . This site is unofficial and not affiliated with Prisma Data, Inc.