分享於

簡介

當您開始使用 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 *不會*繼續處理以查看其他規則是否符合請求。因此,規則的順序非常重要。

在每一行中,欄位以空白字元(空格或 Tab)分隔。雖然將這些欄位格式化為欄通常在視覺上很有幫助,但 PostgreSQL 並不要求這樣做。

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

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

我們將涵蓋的欄位有:

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

連線類型

每筆記錄中的第一個欄位指定要比對的連線請求類型。只有使用指定連線的連線才會符合每個規則。

連線類型必須是以下其中之一:

  • local:具有 local 的記錄比對透過本機 Unix 網域 socket 檔案而不是透過網路建立的連線。出於安全性和效能考量,盡可能優先使用本機連線。
  • host:以 host 開頭的行比對透過網路建立的任何連線請求。這是網路連線的一般萬用比對。透過以下類型可以進行更精細的比對。
  • hostsslhostssl 連線類型比對任何透過網路使用 TLS/SSL 加密建立的連線。這通常是允許外部連線時使用的最佳連線類型。
  • hostnosslhostnossl 類型比對任何未使用 TLS/SSL 保護的網路連線。

從 PostgreSQL 12 開始,新增了對 GSSAPI 連線的支援,引入了以下額外選項:

  • hostgssenchostgssenc 連線類型比對任何使用 GSSAPI 加密的網路連線。此選項僅適用於已經將 GSSAPI 用於安全性的使用者。
  • hostnogssenchostnogssen 類型比對每個未使用 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 安全,但更廣泛地受到支援。目前的實作即使指定了 md5,如果密碼使用 SCRAM 加密,也會自動使用 scram-sha-256
  • 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 主機。

上述某些方法僅適用於特定類型的連線,或適用於已到位其他基礎架構的情況。對於大多數部署,rejectpeerscram-sha-256md5 足以開始使用,其他方法(如 ldap)可根據您的基礎架構使用。

身份驗證選項

在身份驗證方法之後,可能會出現最後一個可選欄位,以提供身份驗證方法的其他選項。此欄位的使用很大程度上取決於所選身份驗證方法的類型。

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

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

設定常見的身份驗證策略

我們介紹了一些主要的身份驗證選項,但您如何使用這些選項來實作合理的策略?在本節中,我們將涵蓋如何設定一些最常見的身份驗證策略。

允許本機使用者連線到相符的資料庫

常見的做法是設定 PostgreSQL,以允許同一機器上的使用者驗證到相同的 PostgreSQL 使用者名稱。例如,使用 peer 身份驗證,如果 PostgreSQL 也具有名為 john 的使用者名稱,則名為 john 的作業系統使用者將能夠自動登入,而無需密碼。

這適用於使用 PostgreSQL socket 檔案建立的任何本機連線。如果您指定任何網路位址,即使它是 127.0.0.1 本機迴路介面,連線也不會使用 socket,並且不會比對 peer 身份驗證行。但是,連線到 localhost 將使用 socket 檔案,並且會比對這些行。

若要允許所有 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 身份驗證驗證到 susan PostgreSQL 使用者,就像它們相符一樣。

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

若要驗證來自 PostgreSQL 伺服器機器的網路連線(非 socket 連線)使用密碼,您需要比對 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 關鍵字用於比對這些複寫連線。任何具有複寫權限的使用者都能夠建立複寫連線。

為了允許所有本機複寫連線,並以反映我們先前用於一般連線的值(Unix socket 連線使用 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 檔案中指定一個 map 檔案

# 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、基礎架構和開發人員工具的文章。他目前與妻子和兩隻兔子住在柏林。他通常不必以第三人稱寫作,這對所有相關方來說都是一種解脫。