使用适用于 PostgreSQL 的可信语言扩展 - Amazon Relational Database Service
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

使用适用于 PostgreSQL 的可信语言扩展

适用于 PostgreSQL 的可信语言扩展是一个用于构建 PostgreSQL 扩展的开源开发套件。它允许您构建高性能 PostgreSQL 扩展,并在您的 RDS for PostgreSQL 数据库实例上安全地运行它们。通过使用适用于 PostgreSQL 的可信语言扩展(TLE),您可以创建 PostgreSQL 扩展,这些扩展遵循已记载的用于扩展 PostgreSQL 功能的方法。有关更多信息,请参阅 PostgreSQL 文档中的将相关对象打包为扩展

TLE 的一个关键好处是,您可以在不提供对 PostgreSQL 实例底层文件系统的访问权限的环境中使用它。以前,安装新扩展需要访问文件系统。TLE 消除了这一约束。它提供了一个开发环境,用于为任何 PostgreSQL 数据库创建新扩展,包括在 RDS for PostgreSQL 数据库实例上运行的扩展。

TLE 旨在防止访问您使用 TLE 创建的扩展的不安全资源。它的运行时环境限制了任何扩展缺陷对单个数据库连接的影响。TLE 还让数据库管理员可以细粒度控制谁可以安装扩展,并为运行扩展提供了权限模型。

以下 RDS for PostgreSQL 版本支持 TLE:

  • 版本 15.2 及更高的 15 版本。

  • 版本 14.5 及更高的 14 版本。

  • 版本 13.12 及更高的 13 版本。

可信语言扩展开发环境和运行时打包为 pg_tle PostgreSQL 扩展,版本 1.0.1。它支持在 JavaScript、Perl、Tcl、PL/pgSQL 和 SQL 中创建扩展。您可以在 RDS for PostgreSQL 数据库实例中安装 pg_tle 扩展,方式与安装其他 PostgreSQL 扩展一样。设置 pg_tle 后,开发人员可以使用它来创建新的 PostgreSQL 扩展,称为 TLE 扩展

在以下主题中,您可以了解有关如何设置可信语言扩展以及如何开始创建自己的 TLE 扩展的信息。

术语

为了帮助您更好地了解可信语言扩展,请查看以下词汇表,了解本主题中使用的术语。

适用于 PostgreSQL 的可信语言扩展

适用于 PostgreSQL 的可信语言扩展是打包为 pg_tle 扩展的开源开发套件的正式名称。它可以在任何 PostgreSQL 系统上使用。有关更多信息,请参阅 GitHub 上的 aws/pg_tle

可信语言扩展

可信语言扩展是适用于 PostgreSQL 的可信语言扩展的简称。本文档中也使用了这个缩写名称及其缩写(TLE)。

可信语言

可信语言是一种具有特定安全属性的编程或脚本语言。例如,可信语言通常限制对文件系统的访问,并限制对指定网络属性的使用。TLE 开发套件旨在支持可信语言。PostgreSQL 支持几种不同的用于创建可信扩展或不可信扩展的语言。有关示例,请参阅 PostgreSQL 文档中的可信和不可信 PL/Perl。当您使用可信语言扩展创建扩展时,该扩展本质上使用可信语言机制。

TLE 扩展

TLE 扩展是使用可信语言扩展(TLE)开发套件创建的 PostgreSQL 扩展。

使用适用于 PostgreSQL 的可信语言扩展的要求

以下是设置和使用 TLE 开发套件的要求。

  • RDS for PostgreSQL 版本 – 仅在 RDS for PostgreSQL 版本 13.12 及更高的 13 版本、14.5 及更高的 14 版本,以及 15.2 及更高的版本上支持可信语言扩展。

  • 需要 rds_superuser 权限 - 要设置和配置 pg_tle 扩展,您的数据库用户角色必须具有 rds_superuser 角色的权限。默认情况下,此角色被授予 postgres 用户,此用户创建 RDS for PostgreSQL 数据库实例

  • 需要自定义数据库参数组 – 您的 RDS for PostgreSQL 数据库实例必须使用自定义数据库参数组进行配置。

创建和应用自定义数据库参数组

使用以下步骤创建自定义数据库参数组,并将 RDS for PostgreSQL 数据库实例配置为使用该参数组。

创建自定义数据库参数组并将其与您的 RDS for PostgreSQL 数据库实例一起使用
  1. 登录 Amazon Web Services Management Console 并通过以下网址打开 Amazon RDS 控制台:https://console.aws.amazon.com/rds/

  2. 从 Amazon RDS 菜单中选择 Parameter groups(参数组)。

  3. 选择创建参数组

  4. Parameter group details(参数组详细信息)页面中,输入以下信息。

    • 对于Parameter group family(参数组系列),选择 postgres14

    • 对于 Type(类型),请选择 DB Parameter Group(数据库参数组)。

    • 对于 Group name(组名称),在操作上下文中为参数组指定一个有意义的名称。

    • 对于 Description(描述),输入有用的描述,以便团队中的其他人可以轻松找到它。

  5. 选择创建。您的自定义数据库参数组是在您的 Amazon Web Services 区域中创建的。现在,您可以按照以下步骤修改 RDS for PostgreSQL 数据库实例以使用它。

  6. 从 Amazon RDS 菜单中选择 Databases(数据库)。

  7. 从列出的列表中选择要与 TLE 结合使用的 RDS for PostgreSQL 数据库实例,然后选择 Modify(修改)。

  8. Modify DB instance settings(修改数据库实例设置)页面中,在 Additional configuration(其他配置)部分中找到 Database options(数据库选项),并从选择器中选择您的自定义数据库参数组。

  9. 选择 Continue(继续)以保存更改。

  10. 选择 Apply immediately(立即应用),这样您就可以继续将 RDS for PostgreSQL 数据库实例设置为使用 TLE。

要继续为系统设置可信语言扩展,请参阅 在 RDS for PostgreSQL 数据库实例中设置可信语言扩展

有关使用数据库参数组的更多信息,请参阅 使用数据库实例中的数据库参数组

在使用 CLI 命令时,您可以通过将您的 Amazon CLI 配置为使用默认 Amazon Web Services 区域来避免指定 --region 参数。有关更多信息,请参阅《Amazon Command Line Interface 用户指南》中的配置基础知识

创建自定义数据库参数组并将其与您的 RDS for PostgreSQL 数据库实例一起使用
  1. 使用 create-db-parameter-group Amazon CLI 命令为您的 Amazon Web Services 区域创建一个基于 postgres14 的自定义数据库参数组。

    对于 Linux、macOS 或 Unix:

    aws rds create-db-parameter-group \ --region aws-region \ --db-parameter-group-name custom-params-for-pg-tle \ --db-parameter-group-family postgres14 \ --description "My custom DB parameter group for Trusted Language Extensions"

    对于 Windows:

    aws rds create-db-parameter-group ^ --region aws-region ^ --db-parameter-group-name custom-params-for-pg-tle ^ --db-parameter-group-family postgres14 ^ --description "My custom DB parameter group for Trusted Language Extensions"

    您的自定义数据库参数组在 Amazon Web Services 区域中可用,因此您可以修改 RDS for PostgreSQL 数据库实例以使用它。

  2. 使用 modify-db-instance Amazon CLI 命令将自定义数据库参数组应用于 RDS for PostgreSQL 数据库实例。此命令立即重启活动实例。

    对于 Linux、macOS 或 Unix:

    aws rds modify-db-instance \ --region aws-region \ --db-instance-identifier your-instance-name \ --db-parameter-group-name custom-params-for-pg-tle \ --apply-immediately

    对于 Windows:

    aws rds modify-db-instance ^ --region aws-region ^ --db-instance-identifier your-instance-name ^ --db-parameter-group-name custom-params-for-pg-tle ^ --apply-immediately

要继续为系统设置可信语言扩展,请参阅 在 RDS for PostgreSQL 数据库实例中设置可信语言扩展

有关更多信息,请参阅 使用参数组

RDS for PostgreSQL 数据库实例中设置可信语言扩展

以下步骤假设您的 RDS for PostgreSQL 数据库实例与自定义数据库参数组相关联。您可以使用 Amazon Web Services Management Console或 Amazon CLI 来执行这些步骤。

当您在 RDS for PostgreSQL 数据库实例中设置可信语言扩展时,您可以将其安装在特定的数据库中,供对该数据库拥有权限的数据库用户使用。

设置可信语言扩展

使用作为 rds_superuser 组(角色)成员的账户执行以下步骤。

  1. 登录 Amazon Web Services Management Console 并通过以下网址打开 Amazon RDS 控制台:https://console.aws.amazon.com/rds/

  2. 在导航窗格中,选择 RDS for PostgreSQL 数据库实例

  3. 打开 的配置选项卡。RDS for PostgreSQL 数据库实例的 Configuration(配置)选项卡。在实例详细信息中,找到 Parameter group(参数组)链接。

  4. 选择此链接以打开与您的 RDS for PostgreSQL 数据库实例关联的自定义参数。

  5. Parameters(参数)搜索字段中,键入 shared_pre 以查找 shared_preload_libraries 参数。

  6. 选择 Edit parameters(编辑参数)以访问属性值。

  7. pg_tle 添加到 Values(值)字段的列表中。使用逗号分隔值列表中的项目。

    
                                添加了 pg_tle 的 shared_preload_libraries 参数的图像。
  8. 重启 RDS for PostgreSQL 数据库实例,以使对 shared_preload_libraries 参数的更改生效。

  9. 当实例可用时,验证 pg_tle 是否已初始化。使用 psql 连接到 RDS for PostgreSQL 数据库实例,然后运行以下命令。

    SHOW shared_preload_libraries; shared_preload_libraries -------------------------- rdsutils,pg_tle (1 row)
  10. 初始化 pg_tle 扩展后,您现在可以创建此扩展了。

    CREATE EXTENSION pg_tle;

    可以使用以下 psql 元命令验证扩展是否已安装。

    labdb=> \dx List of installed extensions Name | Version | Schema | Description ---------+---------+------------+-------------------------------------------- pg_tle | 1.0.1 | pgtle | Trusted-Language Extensions for PostgreSQL plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
  11. 在设置 RDS for PostgreSQL 数据库实例时,将 pgtle_admin 角色授予为其创建的主用户名。如果您接受了默认值,则它就是 postgres

    labdb=> GRANT pgtle_admin TO postgres; GRANT ROLE

    您可以使用 psql 元命令来验证授权是否已完成,如以下示例中所示。输出中仅显示 pgtle_adminpostgres 角色。有关更多信息,请参阅了解 rds_superuser 角色

    labdb=> \du List of roles Role name | Attributes | Member of -----------------+---------------------------------+----------------------------------- pgtle_admin | Cannot login | {} postgres | Create role, Create DB +| {rds_superuser,pgtle_admin} | Password valid until infinity |...
  12. 使用 \q 元命令关闭 psql 会话。

    \q

要开始创建 TLE 扩展,请参阅 示例:使用 SQL 创建可信语言扩展

在使用 CLI 命令时,您可以通过将您的 Amazon CLI 配置为使用默认 Amazon Web Services 区域来避免指定 --region 参数。有关更多信息,请参阅《Amazon Command Line Interface 用户指南》中的配置基础知识

设置可信语言扩展
  1. 使用 modify-db-parameter-group Amazon CLI 命令将 pg_tle 添加到 shared_preload_libraries 参数。

    aws rds modify-db-parameter-group \ --db-parameter-group-name custom-param-group-name \ --parameters "ParameterName=shared_preload_libraries,ParameterValue=pg_tle,ApplyMethod=pending-reboot" \ --region aws-region
  2. 使用 reboot-db-instance Amazon CLI 命令重启 RDS for PostgreSQL 数据库实例并初始化 pg_tle 库。

    aws rds reboot-db-instance \ --db-instance-identifier your-instance \ --region aws-region
  3. 当实例可用时,您可以验证 pg_tle 是否已初始化。使用 psql 连接到 RDS for PostgreSQL 数据库实例,然后运行以下命令。

    SHOW shared_preload_libraries; shared_preload_libraries -------------------------- rdsutils,pg_tle (1 row)

    初始化 pg_tle 后,您现在可以创建扩展了。

    CREATE EXTENSION pg_tle;
  4. 在设置 RDS for PostgreSQL 数据库实例时,将 pgtle_admin 角色授予为其创建的主用户名。如果您接受了默认值,则它就是 postgres

    GRANT pgtle_admin TO postgres; GRANT ROLE
  5. 按如下方式关闭 psql 会话。

    labdb=> \q

要开始创建 TLE 扩展,请参阅 示例:使用 SQL 创建可信语言扩展

适用于 PostgreSQL 的可信语言扩展概述

适用于 PostgreSQL 的可信语言扩展是一个 PostgreSQL 扩展,您可以像设置其他 PostgreSQL 扩展一样,将其安装在 RDS for PostgreSQL 数据库实例中。在下图的 pgAdmin 客户端工具的示例数据库中,您可以查看构成 pg_tle 扩展的部分组件。


                该图显示了构成 TLE 开发套件的部分组件。

您可以查看以下详细信息。

  1. 适用于 PostgreSQL 的可信语言扩展(TLE)开发套件打包为 pg_tle 扩展。因此,pg_tle 添加到安装它的数据库的可用扩展中。

  2. TLE 有它自己的模式,即 pgtle。此模式包含辅助函数(3 个),用于安装和管理您创建的扩展。

  3. TLE 提供了十多个辅助函数,用于安装、注册和管理您的扩展。要了解有关这些函数的更多信息,请参阅 适用于 PostgreSQL 的可信语言扩展的函数参考

pg_tle 扩展的其他组件包含以下各项:

  • pgtle_admin 角色pgtle_admin 角色是在安装 pg_tle 扩展时创建的。此角色获得了相关权限,应视为具有此类权限。我们强烈建议您在向数据库用户授予 pgtle_admin 角色时遵循最低权限原则。换句话说,仅向允许创建、安装和管理新 TLE 扩展(例如 postgres)的数据库用户授予 pgtle_admin 角色。

  • pgtle.feature_infopgtle.feature_info 表是一个受保护的表,其中包含有关您的 TLE、挂钩及其使用的自定义存储过程和函数的信息。如果您有 pgtle_admin 权限,则可以使用以下可信语言扩展函数在表中添加和更新该信息。

RDS for PostgreSQL 创建 TLE 扩展

您可以将使用 TLE 创建的任何扩展安装在安装了 pg_tle 扩展的任何 RDS for PostgreSQL 数据库实例中。pg_tle 扩展的范围限于安装该扩展的 PostgreSQL 数据库。使用 TLE 创建的扩展的范围限于同一个数据库。

使用各种 pgtle 函数安装构成 TLE 扩展的代码。以下可信语言扩展函数全部需要 pgtle_admin 角色。

示例:使用 SQL 创建可信语言扩展

以下示例说明如何创建名为 pg_distance 的 TLE 扩展,该扩展包含一些 SQL 函数,用于使用不同的公式计算距离。在列表中,您可以找到用于计算曼哈顿距离的函数和用于计算欧几里得距离的函数。有关这些公式之间差异的更多信息,请参阅维基百科中的 Taxicab 几何欧几里得几何

如果您按照在 RDS for PostgreSQL 数据库实例中设置可信语言扩展中详述设置了 pg_tle 扩展,则可以在自己的 RDS for PostgreSQL 数据库实例中使用此示例。

注意

您需要拥有 pgtle_admin 角色的权限才能执行此过程。

创建示例 TLE 扩展

以下步骤使用名为 labdb 的示例数据库。该数据库归 postgres 主用户所有。postgres 角色还具有 pgtle_admin 角色的权限。

  1. 使用 psql 连接到 RDS for PostgreSQL 数据库实例

    psql --host=db-instance-123456789012.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password --dbname=labdb
  2. 通过复制以下代码并将其粘贴到 psql 会话控制台中来创建名为 pg_distance 的 TLE 扩展。

    SELECT pgtle.install_extension ( 'pg_distance', '0.1', 'Distance functions for two points', $_pg_tle_$ CREATE FUNCTION dist(x1 float8, y1 float8, x2 float8, y2 float8, norm int) RETURNS float8 AS $$ SELECT (abs(x2 - x1) ^ norm + abs(y2 - y1) ^ norm) ^ (1::float8 / norm); $$ LANGUAGE SQL; CREATE FUNCTION manhattan_dist(x1 float8, y1 float8, x2 float8, y2 float8) RETURNS float8 AS $$ SELECT dist(x1, y1, x2, y2, 1); $$ LANGUAGE SQL; CREATE FUNCTION euclidean_dist(x1 float8, y1 float8, x2 float8, y2 float8) RETURNS float8 AS $$ SELECT dist(x1, y1, x2, y2, 2); $$ LANGUAGE SQL; $_pg_tle_$ );

    您将看到如下输出。

    install_extension --------------- t (1 row)

    构成 pg_distance 扩展的构件现在已安装在您的数据库中。这些构件包括扩展的控制文件和代码,这些项目需要存在,这样才能使用 CREATE EXTENSION 命令创建扩展。换句话说,您仍然需要创建扩展以使其函数可供数据库用户使用。

  3. 要创建扩展,请像使用任何其他扩展一样使用 CREATE EXTENSION 命令。与其他扩展一样,数据库用户需要在数据库中拥有 CREATE 权限。

    CREATE EXTENSION pg_distance;
  4. 要测试 pg_distance TLE 扩展,可以使用它来计算四个点之间的曼哈顿距离

    labdb=> SELECT manhattan_dist(1, 1, 5, 5); 8

    要计算同一组点之间的欧几里得距离,可以使用以下方法。

    labdb=> SELECT euclidean_dist(1, 1, 5, 5); 5.656854249492381

pg_distance 扩展将函数加载到数据库中,并使对数据库具有权限的任何用户都可以使用它们。

修改您的 TLE 扩展

要提高此 TLE 扩展中打包的函数的查询性能,请在其规范中添加以下两个 PostgreSQL 属性。

  • IMMUTABLEIMMUTABLE 属性可确保查询优化程序可以使用优化措施来缩短查询响应时间。有关更多信息,请参阅 PostgreSQL 文档中的函数波动性类别

  • PARALLEL SAFEPARALLEL SAFE 属性是允许 PostgreSQL 在并行模式下运行该函数的另一个属性。有关更多信息,请参阅 PostgreSQL 文档中的 CREATE FUNCTION

在以下示例中,您可以看到如何使用 pgtle.install_update_path 函数向每个函数添加这些属性,以创建 pg_distance TLE 扩展的版本 0.2。有关此函数的更多信息,请参阅 pgtle.install_update_path。您需要拥有 pgtle_admin 角色才能执行此任务。

更新现有 TLE 扩展并指定默认版本
  1. 使用 psql 或其他客户端工具(例如 pgAdmin)连接到 RDS for PostgreSQL 数据库实例

    psql --host=db-instance-123456789012.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password --dbname=labdb
  2. 通过复制以下代码并将其粘贴到 psql 会话控制台中来修改现有 TLE 扩展。

    SELECT pgtle.install_update_path ( 'pg_distance', '0.1', '0.2', $_pg_tle_$ CREATE OR REPLACE FUNCTION dist(x1 float8, y1 float8, x2 float8, y2 float8, norm int) RETURNS float8 AS $$ SELECT (abs(x2 - x1) ^ norm + abs(y2 - y1) ^ norm) ^ (1::float8 / norm); $$ LANGUAGE SQL IMMUTABLE PARALLEL SAFE; CREATE OR REPLACE FUNCTION manhattan_dist(x1 float8, y1 float8, x2 float8, y2 float8) RETURNS float8 AS $$ SELECT dist(x1, y1, x2, y2, 1); $$ LANGUAGE SQL IMMUTABLE PARALLEL SAFE; CREATE OR REPLACE FUNCTION euclidean_dist(x1 float8, y1 float8, x2 float8, y2 float8) RETURNS float8 AS $$ SELECT dist(x1, y1, x2, y2, 2); $$ LANGUAGE SQL IMMUTABLE PARALLEL SAFE; $_pg_tle_$ );

    您看到的响应与以下内容类似。

    install_update_path --------------------- t (1 row)

    您可以将此版本的扩展设置为默认版本,这样,数据库用户在其数据库中创建或更新扩展时就不必指定版本。

  3. 要将 TLE 扩展的修改版本(版本 0.2)指定为默认版本,请使用以下示例所示的 pgtle.set_default_version 函数。

    SELECT pgtle.set_default_version('pg_distance', '0.2');

    有关此函数的更多信息,请参阅 pgtle.set_default_version

  4. 代码准备就绪后,您可以使用 ALTER EXTENSION ... UPDATE 命令以常规方式更新已安装的 TLE 扩展,如此处所示:

    ALTER EXTENSION pg_distance UPDATE;

从数据库中删除 TLE 扩展

您可以使用 DROP EXTENSION 命令删除 TLE 扩展,方法与处理其他 PostgreSQL 扩展的方法相同。删除扩展并不会删除构成扩展的安装文件,这允许用户重新创建扩展。要删除扩展及其安装文件,请执行以下两步过程。

删除 TLE 扩展并删除其安装文件
  1. 使用 psql 或其他客户端工具连接到 RDS for PostgreSQL 数据库实例

    psql --host=.111122223333.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password --dbname=dbname
  2. 像删除任何 PostgreSQL 扩展一样删除此扩展。

    DROP EXTENSION your-TLE-extension

    例如,如果您按照示例:使用 SQL 创建可信语言扩展中的详细说明创建 pg_distance 扩展,则可以按如下方式删除此扩展。

    DROP EXTENSION pg_distance;

    您将看到确认扩展已删除的输出,如下所示。

    DROP EXTENSION

    此时,该扩展在数据库中不再处于活动状态。但是,它的安装文件和控制文件在数据库中仍然可用,因此数据库用户可以根据需要再次创建扩展。

    • 如果您想让扩展文件保持完好,以便数据库用户可以创建您的 TLE 扩展,则可以在此处停止。

    • 如果要删除构成扩展的所有文件,请继续执行下一步。

  3. 要删除扩展的所有安装文件,请使用 pgtle.uninstall_extension 函数。此函数删除扩展的所有代码和控制文件。

    SELECT pgtle.uninstall_extension('your-tle-extension-name');

    例如,要删除所有 pg_distance 安装文件,请使用以下命令。

    SELECT pgtle.uninstall_extension('pg_distance'); uninstall_extension --------------------- t (1 row)

卸载适用于 PostgreSQL 的可信语言扩展

如果您不想再使用 TLE 创建自己的 TLE 扩展,则可以删除 pg_tle 扩展并删除所有构件。此操作包括删除数据库中的所有 TLE 扩展和删除 pgtle 模式。

从数据库中删除 pg_tle 扩展及其模式
  1. 使用 psql 或其他客户端工具连接到 RDS for PostgreSQL 数据库实例

    psql --host=.111122223333.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password --dbname=dbname
  2. 从数据库中删除 pg_tle 扩展。如果数据库中仍在运行您自己的 TLE 扩展,则还需要删除这些扩展。为此,您可以使用 CASCADE 关键字,如以下所示。

    DROP EXTENSION pg_tle CASCADE;

    如果 pg_tle 扩展在数据库中仍未处于活动状态,则无需使用 CASCADE 关键字。

  3. 删除 pgtle 模式。此操作将从数据库中删除所有管理函数。

    DROP SCHEMA pgtle CASCADE;

    该过程完成后,该命令将返回以下内容。

    DROP SCHEMA

    pg_tle 扩展、其模式和函数以及所有构件均已删除。要使用 TLE 创建新扩展,请再次完成设置过程。有关更多信息,请参阅在 RDS for PostgreSQL 数据库实例中设置可信语言扩展

在您的 TLE 扩展中使用 PostgreSQL 挂钩

挂钩是 PostgreSQL 中可用的一种回调机制,它允许开发人员在常规数据库操作期间调用自定义函数或其他例程。TLE 开发套件支持 PostgreSQL 挂钩,因此您可以在运行时将自定义函数与 PostgreSQL 行为集成在一起。例如,您可以使用挂钩将身份验证过程与您自己的自定义代码关联起来,或者根据您的特定需求修改查询规划和执行流程。

您的 TLE 扩展可以使用挂钩。如果挂钩在作用域方面是全局的,则它适用于所有数据库。因此,如果您的 TLE 扩展使用全局挂钩,则需要在用户可以访问的所有数据库中创建 TLE 扩展。

当您使用 pg_tle 扩展构建自己的可信语言扩展时,您可以使用 SQL API 中的可用挂钩来构建扩展的功能。您应该向 pg_tle 注册任何挂钩。对于某些挂钩,您可能还需要设置各种配置参数。例如,可以将 passcode 检查挂钩设置为 on、off 或 require。有关可用 pg_tle 挂钩的特定要求的更多信息,请参阅 适用于 PostgreSQL 的可信语言扩展的挂钩参考

示例:创建使用 PostgreSQL 挂钩的扩展

本节讨论的示例使用 PostgreSQL 挂钩检查在特定 SQL 操作期间提供的密码,并防止数据库用户将其密码设置为 password_check.bad_passwords 表中包含的任何密码。该表包含十大最常用但易于破解的密码选择。

要在 RDS for PostgreSQL 数据库实例中设置此示例,您必须已经安装了可信语言扩展。有关详细信息,请参阅 在 RDS for PostgreSQL 数据库实例中设置可信语言扩展

设置密码检查挂钩示例
  1. 使用 psql 连接到 RDS for PostgreSQL 数据库实例

    psql --host=db-instance-123456789012.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password --dbname=labdb
  2. 密码检查挂钩代码列表中复制代码并将其粘贴到数据库中。

    SELECT pgtle.install_extension ( 'my_password_check_rules', '1.0', 'Do not let users use the 10 most commonly used passwords', $_pgtle_$ CREATE SCHEMA password_check; REVOKE ALL ON SCHEMA password_check FROM PUBLIC; GRANT USAGE ON SCHEMA password_check TO PUBLIC; CREATE TABLE password_check.bad_passwords (plaintext) AS VALUES ('123456'), ('password'), ('12345678'), ('qwerty'), ('123456789'), ('12345'), ('1234'), ('111111'), ('1234567'), ('dragon'); CREATE UNIQUE INDEX ON password_check.bad_passwords (plaintext); CREATE FUNCTION password_check.passcheck_hook(username text, password text, password_type pgtle.password_types, valid_until timestamptz, valid_null boolean) RETURNS void AS $$ DECLARE invalid bool := false; BEGIN IF password_type = 'PASSWORD_TYPE_MD5' THEN SELECT EXISTS( SELECT 1 FROM password_check.bad_passwords bp WHERE ('md5' || md5(bp.plaintext || username)) = password ) INTO invalid; IF invalid THEN RAISE EXCEPTION 'Cannot use passwords from the common password dictionary'; END IF; ELSIF password_type = 'PASSWORD_TYPE_PLAINTEXT' THEN SELECT EXISTS( SELECT 1 FROM password_check.bad_passwords bp WHERE bp.plaintext = password ) INTO invalid; IF invalid THEN RAISE EXCEPTION 'Cannot use passwords from the common common password dictionary'; END IF; END IF; END $$ LANGUAGE plpgsql SECURITY DEFINER; GRANT EXECUTE ON FUNCTION password_check.passcheck_hook TO PUBLIC; SELECT pgtle.register_feature('password_check.passcheck_hook', 'passcheck'); $_pgtle_$ );

    将扩展加载到数据库后,您会看到如下输出。

    install_extension ------------------- t (1 row)
  3. 当仍然连接到数据库时,现在可以创建扩展了。

    CREATE EXTENSION my_password_check_rules;
  4. 您可以使用以下 psql 元命令确认已在数据库中创建扩展。

    \dx List of installed extensions Name | Version | Schema | Description -------------------------+---------+------------+------------------------------------------------------------- my_password_check_rules | 1.0 | public | Prevent use of any of the top-ten most common bad passwords pg_tle | 1.0.1 | pgtle | Trusted-Language Extensions for PostgreSQL plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language (3 rows)
  5. 打开另一个终端会话来使用 Amazon CLI。您需要修改您的自定义数据库参数组才能开启密码检查挂钩。为此,请使用 modify-db-parameter-group CLI 命令,如以下示例中所示。

    aws rds modify-db-parameter-group \ --region aws-region \ --db-parameter-group-name your-custom-parameter-group \ --parameters "ParameterName=pgtle.enable_password_check,ParameterValue=on,ApplyMethod=immediate"

    成功开启此参数后,您将看到如下输出。

    ( "DBParameterGroupName": "docs-lab-parameters-for-tle" }

    对参数组设置进行的更改可能需要几分钟才能生效。但是,此参数是动态的,因此您无需重新启动 RDS for PostgreSQL 数据库实例,即可使该设置生效。

  6. 打开 psql 会话并查询数据库,以验证密码检查挂钩已开启。

    labdb=> SHOW pgtle.enable_password_check; pgtle.enable_password_check ----------------------------- on (1 row)

密码检查挂钩现处于活动状态。您可以通过创建新角色并使用其中一个错误密码来对其进行测试,如以下示例中所示。

CREATE ROLE test_role PASSWORD 'password'; ERROR: Cannot use passwords from the common password dictionary CONTEXT: PL/pgSQL function password_check.passcheck_hook(text,text,pgtle.password_types,timestamp with time zone,boolean) line 21 at RAISE SQL statement "SELECT password_check.passcheck_hook( $1::pg_catalog.text, $2::pg_catalog.text, $3::pgtle.password_types, $4::pg_catalog.timestamptz, $5::pg_catalog.bool)"

对输出设置了格式以便于阅读。

以下示例显示,pgsql 交互式元命令 \password 行为也受到密码检查挂钩的影响。

postgres=> SET password_encryption TO 'md5'; SET postgres=> \password Enter new password for user "postgres":***** Enter it again:***** ERROR: Cannot use passwords from the common password dictionary CONTEXT: PL/pgSQL function password_check.passcheck_hook(text,text,pgtle.password_types,timestamp with time zone,boolean) line 12 at RAISE SQL statement "SELECT password_check.passcheck_hook($1::pg_catalog.text, $2::pg_catalog.text, $3::pgtle.password_types, $4::pg_catalog.timestamptz, $5::pg_catalog.bool)"

如果需要,可以删除此 TLE 扩展并卸载其源文件。有关更多信息,请参阅从数据库中删除 TLE 扩展

密码检查挂钩代码列表

此处显示的示例代码定义了 my_password_check_rules TLE 扩展的规范。当您复制此代码并将其粘贴到数据库中时,my_password_check_rules 扩展的代码将加载到数据库中,并注册 password_check 挂钩以供扩展使用。

SELECT pgtle.install_extension ( 'my_password_check_rules', '1.0', 'Do not let users use the 10 most commonly used passwords', $_pgtle_$ CREATE SCHEMA password_check; REVOKE ALL ON SCHEMA password_check FROM PUBLIC; GRANT USAGE ON SCHEMA password_check TO PUBLIC; CREATE TABLE password_check.bad_passwords (plaintext) AS VALUES ('123456'), ('password'), ('12345678'), ('qwerty'), ('123456789'), ('12345'), ('1234'), ('111111'), ('1234567'), ('dragon'); CREATE UNIQUE INDEX ON password_check.bad_passwords (plaintext); CREATE FUNCTION password_check.passcheck_hook(username text, password text, password_type pgtle.password_types, valid_until timestamptz, valid_null boolean) RETURNS void AS $$ DECLARE invalid bool := false; BEGIN IF password_type = 'PASSWORD_TYPE_MD5' THEN SELECT EXISTS( SELECT 1 FROM password_check.bad_passwords bp WHERE ('md5' || md5(bp.plaintext || username)) = password ) INTO invalid; IF invalid THEN RAISE EXCEPTION 'Cannot use passwords from the common password dictionary'; END IF; ELSIF password_type = 'PASSWORD_TYPE_PLAINTEXT' THEN SELECT EXISTS( SELECT 1 FROM password_check.bad_passwords bp WHERE bp.plaintext = password ) INTO invalid; IF invalid THEN RAISE EXCEPTION 'Cannot use passwords from the common common password dictionary'; END IF; END IF; END $$ LANGUAGE plpgsql SECURITY DEFINER; GRANT EXECUTE ON FUNCTION password_check.passcheck_hook TO PUBLIC; SELECT pgtle.register_feature('password_check.passcheck_hook', 'passcheck'); $_pgtle_$ );

在 TLE 中使用自定义数据类型

PostgreSQL 支持注册新的基本类型(也称为标量类型)的命令,以便高效地处理数据库中的复杂数据结构。基本类型允许您自定义在内部存储数据的方式,以及如何将其与外部文本表示形式相互转换。在扩展 PostgreSQL 以支持功能域时,这些自定义数据类型非常有用,在这种情况下,诸如数字或文本之类的内置类型无法提供足够的搜索语义。

RDS for PostgreSQL 允许您在可信语言扩展中创建自定义数据类型,并为这些新的数据类型定义支持 SQL 和索引操作的函数。自定义数据类型适用于以下版本:

  • RDS for PostgreSQL 15.4 和更高的 15 版本

  • RDS for PostgreSQL 14.9 和更高的 14 版本

  • RDS for PostgreSQL 13.12 和更高的 13 版本

有关更多信息,请参阅可信语言库类型