开发版本: 19 / devel
此文档适用于不受支持的 PostgreSQL 版本。
您可能需要查看当前版本的相同页面,或上面列出的其他受支持版本。

50.4. 自定义 HBA 选项 #

和其他预加载库一样,验证器模块可以为用户在 postgresql.conf中配置 自定义 GUC 参数。 不过,有时可能希望在更细粒度的层面配置行为(例如针对某个特定签发者 或某一组用户),而不是全局配置。

PostgreSQL 19 开始,验证器实现可以定义供 pg_hba.conf 内使用的自定义选项。这些选项会 validator.option 的形式提供给用户。 注册和获取自定义选项的 API 如下所述。

50.4.1. 选项 API #

模块在 startup_cb 回调期间使用 RegisterOAuthHBAOptions() 注册自定义 HBA 选项名:

/*
 * Register a list of custom option names for use in pg_hba.conf. For each name
 * "foo" registered here, that option will be provided as "validator.foo" in
 * the HBA.
 *
 * Valid option names consist of alphanumeric ASCII, underscore (_), and hyphen
 * (-). Invalid option names will be ignored with a WARNING logged at
 * connection time.
 *
 * This function may only be called during the startup_cb callback. Multiple
 * calls are permitted, which will append to the existing list of registered
 * options; options cannot be unregistered.
 *
 * Parameters:
 *
 * - state: the state pointer passed to the startup_cb callback
 * - num:   the number of options in the opts array
 * - opts:  an array of null-terminated option names to register
 *
 * The list of option names is copied internally, and the opts array is not
 * required to remain valid after the call.
 */
void RegisterOAuthHBAOptions(ValidatorModuleState *state, int num,
                             const char *opts[]);

如果设置了某个选项,可以随后使用 GetOAuthHBAOption() 获取它的值:

/*
 * Retrieve the string value of an HBA option which was registered via
 * RegisterOAuthHBAOptions(). Usable only during validate_cb or shutdown_cb.
 *
 * If the user has set the corresponding option in pg_hba.conf, this function
 * returns that value as a null-terminated string, which must not be modified
 * or freed. NULL is returned instead if the user has not set this option, if
 * the option name was not registered, or if this function is incorrectly called
 * during the startup_cb.
 *
 * Parameters:
 *
 * - state:   the state pointer passed to the validate_cb/shutdown_cb callback
 * - optname: the name of the option to retrieve
 */
const char *GetOAuthHBAOption(const ValidatorModuleState *state,
                              const char *optname);

示例用法见 Section 50.4.3

50.4.2. 限制 #

  • 选项名仅限 ASCII 字母数字字符、下划线(_)和连字符(-)。

  • 选项值始终是自由格式字符串(与支持数值、布尔值和枚举的自定义 GUC 不同)。

  • 服务器在重新载入配置时无法检查选项名和值。pg_hba.conf 中任何未注册的选项都会导致连接失败。因此,每个模块都有责任按需记录并验证选项值的语法。 [19]

50.4.3. 示例用法 #

对于一个假想模块,选项 foobar 可以这样注册:

static void
validator_startup(ValidatorModuleState *state)
{
    static const char *opts[] = {
        "foo",      /* description of access privileges */
        "bar",      /* magic URL for additional administrator powers */
    };

    RegisterOAuthHBAOptions(state, lengthof(opts), opts);

    /* ...other setup... */
}

然后,pg_hba.conf 中的下列示例条目就可以使用这些选项:

# TYPE   DATABASE   USER   ADDRESS    METHOD
hostssl  postgres   admin  0.0.0.0/0  oauth issuer=https://admin.example.com \
                                            scope="pg-admin openid email" \
                                            map=oauth-email \
                                            validator.foo="admin access" \
                                            validator.bar=https://magic.example.com

hostssl  postgres   all    0.0.0.0/0  oauth issuer=https://www.example.com \
                                            scope="pg-user openid email" \
                                            map=oauth-email \
                                            validator.foo="user access"

模块可以在验证期间从 HBA 中获取这些选项设置:

static bool
validate_token(const ValidatorModuleState *state,
               const char *token, const char *role,
               ValidatorModuleResult *res)
{
    const char *foo = GetOAuthHBAOption(state, "foo"); /* "admin access" or "user access" */
    const char *bar = GetOAuthHBAOption(state, "bar"); /* "https://magic.example.com" or NULL */

    if (bar && !is_valid_url(bar))
    {
        res->error_detail = psprintf("validator.bar (\"%s\") is not a valid URL.", bar);
        return false;
    }

    /* proceed to validate token */
}

当同时使用多个验证器时,它们各自注册的选项列表彼此独立:

in postgresql.conf:
oauth_validator_libraries = 'example_org, my_validator'

in pg_hba.conf:
# TYPE   DATABASE   USER   ADDRESS    METHOD
hostssl  postgres   admin  0.0.0.0/0  oauth issuer=https://admin.example.com \
                                            scope="pg-admin openid email" \
                                            map=oauth-email \
                                            validator=my_validator \
                                            validator.foo="admin access" \
                                            validator.bar=https://magic.example.com

hostssl  postgres   all    0.0.0.0/0  oauth issuer=https://www.example.org \
                                            scope="pg-user openid profile" \
                                            validator=example_org \
                                            delegate_ident_mapping=1 \
                                            validator.magic=on \
                                            validator.more_magic=off


[19] 如果模块在 validate_cb 期间发现无效的选项值,建议通过将 result->error_detail 设为问题描述并返回 false, 来报告内部错误