简介
使用 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 OPTIONSlocal all postgres peerlocal all all peerhost all all 127.0.0.1/32 md5host all all ::1/128 md5local replication all peerhost replication all 127.0.0.1/32 md5host replication all ::1/128 md5
让我们看看不同字段的含义以及文件内容的解释方式。
pg_hba.conf 文件的结构和解释方式
pg_hba.conf 文件中的每一行都描述了客户端向系统进行身份验证的方式。每行的大部分内容描述了用于与传入连接请求进行比较的匹配条件。最后几个组件指定了允许的身份验证方法以及身份验证所需的任何选项。
当 PostgreSQL 根据身份验证规则评估连接请求时,它会按顺序从上到下进行。如果某行中的配置与连接请求的特征匹配,PostgreSQL 将使用该行中指定的身份验证信息来决定是否对客户端进行身份验证。
如果客户端成功通过身份验证,将建立连接。如果身份验证失败,连接将被拒绝。PostgreSQL 不会 继续处理以查看是否有其他规则匹配请求。因此,规则的顺序很重要。
在每一行中,字段通过空白符(空格或制表符)分隔。尽管将这些字段格式化为列通常有助于视觉理解,但 PostgreSQL 不要求这样做。
pg_hba.conf 文件中每个字段的含义
既然您对文件结构和解释方式有了一些了解,我们就可以开始讨论每个字段的含义了。
我们将介绍的字段有
- 连接类型
- 数据库
- 用户名
- 地址
- 身份验证方法
- 身份验证方法的选项
连接类型
每条记录的第一个字段指定要匹配的连接请求类型。只有使用指定连接的请求才会匹配每条规则。
连接类型必须是以下之一
local:带有local的记录匹配通过本地 Unix 域套接字文件而非网络建立的连接。出于安全和性能原因,如果可能,首选本地连接。host:以host开头的行匹配任何通过网络发出的连接请求。这是网络连接的通用捕获。使用以下类型可以进行更精细的匹配。hostssl:hostssl连接类型匹配任何通过 TLS/SSL 加密网络建立的连接。这通常是在允许外部连接时使用的最佳连接类型。hostnossl:hostnossl类型匹配任何未通过 TLS/SSL 保护的网络连接。
从 PostgreSQL 12 开始,还增加了对 GSSAPI 连接的支持,引入了这些额外的选项
hostgssenc:hostgssenc连接类型匹配任何使用 GSSAPI 加密的网络连接。此选项仅适用于已经使用 GSSAPI 进行安全的场景。hostnogssenc:hostnogssen类型匹配所有不使用 GSSAPI 加密的网络连接。
数据库
下一个字段指定请求试图访问的数据库。连接请求中指定的数据库必须满足此列中的值,才能使该行匹配。
值可以是以下任何一个
all:数据库值为all是一个全能值,匹配任何请求的数据库。如果您不希望当前匹配规则评估数据库值,这很有用。sameuser:sameuser值匹配请求的数据库和用户名相同的连接。samerole:如果指定的用户是与请求数据库同名角色的成员,则samerole数据库值将匹配该连接。replication:使用replication值将匹配任何用于数据库复制的传入连接。用于复制的连接不提供数据库目标,因此这会匹配复制请求。- [特定数据库名称]:您还可以提供一个或多个特定的数据库名称进行匹配。这些只会在请求列出的数据库之一时匹配连接。您可以用逗号分隔多个数据库名称,或者通过在文件名前加上
@符号来指定从文件读取名称。
用户
下一个字段用于与连接请求提供的用户进行匹配。连接的用户值必须满足规则的用户字段才能匹配该规则。
用户字段可以采用以下选项
all:值all告诉 PostgreSQL,连接的用户参数中的任何值都满足此规则的用户要求。- [特定用户或组名]:用户字段的唯一其他选项是提供特定用户、用户列表或组。多个用户可以用逗号分隔值来指定。如果名称以
+符号开头,则将其解释为组名而不是用户名。在这种情况下,如果请求的用户是规则指定的组成员,则规则将匹配。同样,您可以通过提供以@符号开头的文件名,而不是直接提供值,来告诉 PostgreSQL 从文件读取值。
地址
对于所有以 host 开头的连接类型(host、hostssl 和 hostnossl,以及 PostgreSQL 12 及更高版本中的 hostgssenc 和 hostnogssenc),紧接着是一个地址字段。对于 local 连接,此字段被跳过。
地址字段指定客户端机器的地址或与连接地址匹配的模式。这意味着连接根据其来源进行评估。连接的来源必须满足规则的地址值才能匹配该规则。
地址字段可以用以下任何一个填充
all:地址值all告诉 PostgreSQL 任何客户端地址都将满足此条件。samehost:值samehost用于表示来自服务器自身 IP 地址之一的任何网络连接都应匹配。samenet:samenet值表示来自服务器网络子网的任何 IP 地址都将匹配。- [CIDR IP 地址范围]:您还可以使用 CIDR 符号提供 IP 地址范围。这可以指定单个 IP 地址(使用 IPv4 地址的
/32子网或 IPv6 地址的/128子网)或通过提供更广泛的 CIDR 掩码来指定地址范围。IP 地址范围仅匹配使用指定 IP 协议从指定范围内的客户端连接。 - [主机名]:也可以直接指定主机名。在这种情况下,客户端的主机名将通过正向和反向 DNS 查询进行评估,以确保其解析符合预期。如果指定的主机名以点开头,则在该域上正确解析的任何主机都将满足要求。
身份验证方法
如果连接满足所有先前的匹配条件,则应用给定的身份验证方法。这是每行中的下一个字段。
身份验证方法是 PostgreSQL 决定是否接受匹配规则的连接的方式。它可以设置为以下任何选项
trust:trust值立即接受连接,无需进一步要求。这假设已设置其他外部身份验证方法。在大多数情况下不推荐使用。reject:reject值立即拒绝连接。这主要用于过滤掉匹配不需要模式的连接。scram-sha-256:scram-sha-256方法将使用SCRAM-SHA-256身份验证检查用户提供的密码。如果所有客户端都支持它,这是当前密码身份验证最安全的选项。md5:md5方法也检查用户密码。此方法不如scram-sha-256安全,但支持范围更广。如果密码使用 SCRAM 加密,即使指定md5,当前实现也会自动使用scram-sha-256。password:password方法是最不安全的密码身份验证方法。它以明文形式发送密码,除非连接使用 TLS/SSL 加密整个连接,否则不应使用。gss:gss方法使用 GSSAPI 进行身份验证。这可以用于身份验证,无论连接是否使用 GSSAPI 加密。这允许通过 Kerberos 和类似软件进行身份验证。sspi:sspi方法使用仅限 Windows 的安全支持提供程序接口 API 来验证客户端。ident:ident方法向客户端的 ident 服务器检查发起连接的用户。由于这依赖于客户端机器,因此它只能用于客户端机器受到严格控制的受信任网络。peer:peer身份验证方法用于本地连接。它向本地操作系统询问客户端的系统用户名。它检查该名称是否与请求的数据库名称匹配。ldap:ldap方法通过使用 LDAP 服务器验证用户名和密码来进行身份验证。radius:选择radius以使用 RADIUS 服务器检查用户名和密码组合。cert:cert方法使用 TLS/SSL 客户端证书对客户端进行身份验证。这仅适用于 TLS/SSL 连接。客户端证书必须是有效且受信任的证书才能被接受。pam:pam选项会将身份验证委托给操作系统的 PAM 服务。bsd:bsd方法使用 BSD 身份验证服务来验证用户名和密码。此方法仅在 OpenBSD 主机上可用。
上述某些方法仅适用于特定类型的连接或在存在额外基础设施的情况下。对于大多数部署,reject、peer 和 scram-sha-256 或 md5 足以开始,根据您的基础设施,还可以使用其他方法,例如 ldap。
身份验证选项
在身份验证方法之后,可能会出现一个可选的最终列,用于为身份验证方法提供附加选项。此列的使用很大程度上取决于所选的身份验证方法类型。
对于引用外部服务器的身份验证方法,这些选项通常指定主机和连接信息,以便 PostgreSQL 可以成功查询身份验证服务。另一个适用于许多身份验证方法的常见选项是 map 参数,它允许您在系统和 PostgreSQL 数据库用户名之间进行转换。
每种身份验证方法都有自己的一套有效选项。请务必查阅 PostgreSQL 文档中每种方法页面上的适用选项。
配置常用身份验证策略
我们已经介绍了一些主要的身份验证选项,但是如何使用这些选项来实现合理的策略呢?在本节中,我们将介绍如何配置一些最常见的身份验证策略。
允许本地用户连接到匹配的数据库
通常会配置 PostgreSQL 以允许同一机器上的用户向相同的 PostgreSQL 用户名进行身份验证。例如,使用 peer 身份验证,名为 john 的操作系统用户将能够自动登录而无需密码,如果 PostgreSQL 也有名为 john 的用户名。
这适用于使用 PostgreSQL 套接字文件建立的任何本地连接。如果您指定任何网络地址,即使它是 127.0.0.1 本地回环设备,连接也不会使用套接字,也不会匹配 peer 身份验证行。然而,连接到 localhost 将使用套接字文件并匹配这些行。
要允许所有 PostgreSQL 用户通过匹配的操作系统用户进行身份验证,请添加一行匹配 local 连接类型、允许所有数据库和用户名并使用 peer 身份验证的规则
# TYPE DATABASE USER ADDRESS METHOD OPTIONSlocal all all peer
如果您想将此限制为只有 john 和 sue PostgreSQL 用户可以通过这种方式进行身份验证,请限制 USER 列的范围
# TYPE DATABASE USER ADDRESS METHOD OPTIONSlocal all john,sue peer
如果您需要允许名为 sue 的操作系统用户向名为 susan 的数据库用户进行身份验证,您可以在行末指定一个 map 选项。选择一个映射名称来标识此映射
# TYPE DATABASE USER ADDRESS METHOD OPTIONSlocal all john,sue peer map=my-map-name
然后,您可以打开同一目录中的 pg_ident.conf 文件来映射您的用户
vim pg_ident.conf
通过在此文件中添加一行,指定您选择的映射名称、操作系统用户名和 PostgreSQL 用户名(用空格分隔),来创建您需要的映射
# MAPNAME SYSTEM-USERNAME PG-USERNAMEmy-map-name sue susan
现在,操作系统 sue 将能够通过 peer 身份验证向 PostgreSQL 用户 susan 进行身份验证,就像它们匹配一样。
允许使用密码从同一机器进行网络连接
要使用密码对来自 PostgreSQL 服务器机器的网络连接(非套接字连接)进行身份验证,您需要匹配 host 连接类型而不是 local。然后,您可以将可接受的地址限制为本地回环设备,并允许用户使用 md5 或 scram-sha-256 进行身份验证。
例如,如果 PostgreSQL 所在的机器上的用户尝试通过指定 127.0.0.1 作为主机进行连接,PostgreSQL 可以执行密码身份验证。
要进行此设置,我们需要使用 host 连接类型。接下来,我们需要指定可接受的地址范围。由于此规则应该只匹配本地连接,我们将指定本地回环设备。我们将不得不添加两条单独的行来匹配 IPv4 和 IPv6 回环设备。
之后,您可以指定要用于身份验证的密码方案。scram-sha-256 方法更安全,但 md5 方法支持更广泛。
完成的身份验证行将如下所示
# TYPE DATABASE USER ADDRESS METHOD OPTIONShost all all 127.0.0.1/32 md5host all all ::1/128 md5
您可以通过将相应列从 all 更改为逗号分隔的特定实体列表,来限制允许使用此方法进行身份验证的数据库或用户。
允许自动维护
定期执行各种自动化维护任务。为了确保这些操作能够按预期进行身份验证和运行,您需要确保管理员帐户能够非交互式地进行身份验证。
默认情况下,postgres 帐户配置为使用 peer 身份验证。这一行很可能已经存在于您的 pg_hba.conf 文件中
# TYPE DATABASE USER ADDRESS METHOD OPTIONSlocal all postgres peer
请确保您的文件中存在此行或类似行,特别是当您更改许多其他身份验证方法时。
允许用于复制的连接
复制是一种特殊的进程,通常频繁地将数据从一个数据库复制到另一个数据库。与其他类型的连接不同,复制连接不指定它们要连接的特定数据库。
数据库列中的 replication 关键字用于匹配这些复制连接。任何具有复制权限的用户都能够建立复制连接。
为了允许所有本地复制连接,其方式与我们之前用于常规连接的值(Unix 套接字连接的 peer 和本地网络连接的 md5)相对应,我们可以添加以下行
# TYPE DATABASE USER ADDRESS METHOD OPTIONSlocal replication all peerhost replication all 127.0.0.1/32 md5host replication all ::1/128 md5
要允许从其他位置进行复制,您可以添加其他地址。例如,要允许从本地 192.0.2.0/24 网络上的任何机器进行复制,您可以添加如下一行
# TYPE DATABASE USER ADDRESS METHOD OPTIONShost replication all 192.0.2.0/24 md5
这将允许来自该网络内机器的任何复制连接使用 md5 加密的密码进行身份验证。
允许使用密码从本地网络进行连接
上面,我们演示了如何为本地复制连接配置密码身份验证。这可以推广到允许任何本地网络连接的密码身份验证。
要允许来自本地 192.0.2.0/24 网络的任何连接进行 md5 密码身份验证,您可以添加如下一行
# TYPE DATABASE USER ADDRESS METHOD OPTIONShost 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 OPTIONShostssl 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 OPTIONShostssl all all all cert
通过此配置,服务器将不再提示用户输入密码,而是要求提供有效的 SSL 证书。证书的通用名称 (CN) 字段必须与请求的数据库用户匹配,否则需要使用 map 文件进行配置。
例如,对于 CN 为 katherine 的证书要向名为 kate 的 PostgreSQL 用户进行身份验证,您需要在 pg_hba.conf 文件中指定一个映射文件
# TYPE DATABASE USER ADDRESS METHOD OPTIONShostssl all all all cert map=my-map-name
之后,您需要编辑 pg_ident.conf 文件以明确地将这两个用户映射在一起
vim pg_ident.conf
# MAPNAME SYSTEM-USERNAME PG-USERNAMEmy-map-name katherine kate
您可以在 PostgreSQL 关于 TLS/SSL 客户端证书的文档中了解如何创建和配置客户端证书。
结论
在本指南中,我们从服务器端介绍了 PostgreSQL 身份验证。我们演示了如何修改 PostgreSQL 实例的配置以更改允许客户端进行身份验证的方式。在讨论了身份验证文件中可用的不同选项后,我们介绍了如何使用我们之前学到的知识实现一些常见的身份验证策略。
了解如何配置身份验证,结合理解如何使用 PostgreSQL 客户端连接,可以您授予合法客户端访问权限,同时防范不必要的连接。此配置是保护数据库实例和防止可能阻碍操作的破坏性登录问题的重要组成部分。
