跳转至

shibboleth: Shibboleth Auth Request module for NGINX

安装

您可以在任何基于 RHEL 的发行版中安装此模块,包括但不限于:

  • RedHat Enterprise Linux 7、8、9 和 10
  • CentOS 7、8、9
  • AlmaLinux 8、9
  • Rocky Linux 8、9
  • Amazon Linux 2 和 Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install nginx-module-shibboleth
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install nginx-module-shibboleth

通过在 /etc/nginx/nginx.conf 顶部添加以下内容来启用模块:

load_module modules/ngx_http_shibboleth_module.so;

本文档描述了 nginx-module-shibboleth v2.0.2,于 2023 年 5 月 26 日发布。


image

此模块允许 Nginx 与 Shibboleth 通过 Shibboleth 的 FastCGI 授权器一起工作。此模块需要特定的配置才能正常工作,以及系统上可用的 Shibboleth FastCGI 授权器应用程序。它旨在与 Apache 的 mod_shib 的某些部分相似,尽管 Shibboleth 的授权和身份验证设置是通过 shibboleth2.xml 配置的,而不是在 Web 服务器配置中。

通过在 location 块中配置此模块,传入请求将在 Nginx 中根据对 Shibboleth FastCGI 授权器的子请求结果进行授权。在此过程中,此模块可以用于将成功授权器响应中的用户属性复制到 Nginx 的原始请求中,作为头部或环境参数供任何后端应用程序使用。如果授权不成功,授权器响应状态和头部将返回给客户端,拒绝访问或相应地重定向用户的浏览器(例如,如果配置了 WAYF 页面)。

此模块在访问阶段工作,因此可以通过 satisfy 指令与其他访问模块(如 accessauth_basic)结合使用。此模块也可以与 ngx_http_auth_request_module 一起编译,但在同一 location 块中使用这两个模块未经测试且不建议。

请阅读下面的 行为 以了解更多信息,并查阅 配置 以获取有关使用头部进行属性时避免欺骗的重要说明。

有关此模块为何是专用模块的更多信息,请参见 https://forum.nginx.org/read.php?2,238523,238523#msg-238523

指令

以下指令将添加到您的 Nginx 配置文件中。下面提到的上下文显示了它们可以添加的位置。

shib_request \<uri>|off | 上下文: httpserverlocation 默认值: off

启用 Shibboleth 授权请求模块并设置将请求授权的 URI。配置的 URI 应指向您的 Shibboleth FastCGI 授权器的 Nginx 位置块。

来自对配置 URI 的子请求的响应的 HTTP 状态和头部将根据 FastCGI 授权器规范 返回给用户。一个(可能显著的)警告是,由于 Nginx 当前在处理子请求时的操作方式(授权器实际上所需的),请求体将 被转发到授权器,类似地,来自授权器的响应体将 返回给客户端。

配置的 URI 不限于使用 FastCGI 后端生成响应。然而,这在测试或其他情况下可能很有用,因为您可以使用 Nginx 内置的 returnrewrite 指令生成合适的响应。此外,此模块可以与 任何 FastCGI 授权器一起使用,尽管上述警告可能会影响其操作。

[!WARNING] shib_request 指令不再需要 shib_authorizer 标志。必须删除此标志以启动 Nginx。无需其他更改。

shib_request_set \<variable> \<value> 上下文: httpserverlocation 默认值: none

在授权请求完成后,将 variable 设置为指定的 valuevalue 可以包含来自授权请求响应的变量。例如,$upstream_http_*$upstream_status 和在 nginx_http_upstream_module 文档中提到的任何其他变量。

此指令可用于将 Shibboleth 属性引入后端应用程序的环境中,例如 FastCGI PHP 应用程序的 $_SERVER,并且这是推荐的方法。有关示例,请参见 配置 文档。

shib_request_use_headers on|off | 上下文: httpserverlocation 默认值: off

[!NOTE] 在 v2.0.0 中添加。

将 Shibboleth 授权器响应中的属性复制到主请求作为头部,使其可供上游服务器和应用程序使用。仅在您的上游/应用程序不支持通过 shib_request_set 的服务器参数时使用此选项。

启用此设置后,以 Variable-\* 开头的授权器响应头将被提取,去掉头部名称中的 Variable- 子字符串,并在发送到后端之前复制到主请求中。例如,授权器响应头 Variable-Commonname: John Smith 将导致 Commonname: John Smith 被添加到主请求中,从而发送到后端。

注意欺骗 - 您必须确保您的后端应用程序受到保护,以防止头部注入。请查阅 配置 示例以了解如何实现这一点。

配置

有关配置 Nginx/Shibboleth 环境的完整详细信息,请参见文档 https://github.com/nginx-shib/nginx-http-shibboleth/blob/master/CONFIG.rst

一个示例 server 块包含以下内容:

#FastCGI 授权器用于授权请求模块
location = /shibauthorizer {
    internal;
    include fastcgi_params;
    fastcgi_pass unix:/opt/shibboleth/shibauthorizer.sock;
}

#FastCGI 响应器
location /Shibboleth.sso {
    include fastcgi_params;
    fastcgi_pass unix:/opt/shibboleth/shibresponder.sock;
}

## 使用 ``shib_request_set`` 指令,我们可以将属性引入
## 后端应用程序的环境变量。在此示例中,我们
## 设置 ``fastcgi_param``,但这可以是任何支持参数的 Nginx 后端
## (通过使用适当的 *_param 选项)
#
## ``shib_fastcgi_params`` 是一组可选的默认参数,
## 可在此存储库的 ``includes/`` 目录中找到。
#
## 除非您的后端应用程序不支持服务器参数或特别需要头部,
## 否则选择此类型的配置。
location /secure-environment-vars {
    shib_request /shibauthorizer;
    include shib_fastcgi_params;
    shib_request_set $shib_commonname $upstream_http_variable_commonname;
    shib_request_set $shib_email $upstream_http_variable_email;
    fastcgi_param COMMONNAME $shib_commonname;
    fastcgi_param EMAIL $shib_email;
    fastcgi_pass unix:/path/to/backend.socket;
}

## 一个安全的位置。所有传入请求查询 Shibboleth FastCGI 授权器。
## 注意性能问题和欺骗!
#
## 对于 ``proxy_pass`` 应用程序或不支持服务器参数的后端,
## 选择此类型的配置。
location /secure {
    shib_request /shibauthorizer;
    shib_request_use_headers on;

    # Shibboleth 的属性由 FastCGI
    # 授权器作为头部引入,因此我们必须防止欺骗。
    # ``shib_clear_headers`` 是一组默认的头部指令,
    # 可在此存储库的 `includes/` 目录中找到。
    include shib_clear_headers;

    # 添加您的应用程序使用的 *所有* 属性,包括所有
    # 变体。
    more_clear_input_headers 'displayName' 'mail' 'persistent-id';

    # 此后端应用程序将接收 Shibboleth 变量作为请求
    # 头部(来自 Shibboleth 的 FastCGI 授权器)
    proxy_pass http://localhost:8080;
}

请注意,我们使用 headers-more-nginx-module 来清除潜在危险的输入头部并避免欺骗的可能性。带环境变量的后一个示例不易受到头部欺骗,只要后端仅从环境参数读取数据即可。

可以使用 default configuration 清除 Shibboleth 授权器的基本头部,但您必须确保为应用程序使用的所有属性编写自己的清除指令。请记住,一些应用程序会尝试从环境中读取 Shibboleth 属性,然后回退到头部,因此即使您不使用 shib_request_use_headers,也要检查应用程序的代码。

使用 shib_request_set,可以使用 default params 文件,您可以将其作为 Nginx include 使用,以确保所有核心 Shibboleth 变量从 FastCGI 授权器传递到应用程序。包含许多默认属性,因此请删除应用程序不需要的属性,并添加所需的 Federation 或 IDP 属性。此默认参数文件可以通过简单地将 fastcgi_param 指令更改为 uwsgi_paramscgi_param 等来重复使用于非 FastCGI 的上游。

注意事项

  • 子请求,例如 Shibboleth 授权请求,不会通过头部过滤器处理。这意味着像 add_header 这样的内置指令如果作为 /shibauthorizer 块的一部分配置,将 起作用。如果您需要操作子请求头部,请使用来自 headers-more 模块的 more_set_headers

请参见 https://forum.nginx.org/read.php?29,257271,257272#msg-257272

行为

此模块在可能的情况下遵循 FastCGI 授权器规范,但有一些显著的偏差 - 这是有充分理由的。行为如下:

  • 授权器子请求包含原始请求的所有方面,除了请求体,因为 Nginx 不支持请求体的缓冲。由于 Shibboleth FastCGI 授权器不考虑请求体,因此这不是问题。

  • 如果授权器子请求返回 200 状态,则允许访问。

如果启用了 shib_request_use_headers,并且提取以 Variable-\* 开头的响应头,去掉头部名称中的 Variable- 子字符串,并复制到主请求中。其他未以 Variable- 开头的授权器响应头和响应体将被忽略。FastCGI 规范要求将 Variable-* 名称值对包含在 FastCGI 环境中,但我们将其作为头部传递,以便可以与 任何 后端(例如 proxy_pass)一起使用,而不仅仅限于 FastCGI 应用程序。通过将 Variable-* 数据作为头部传递,我们最终遵循了 Apache 中 mod_shibShibUseHeaders On 的行为,该行为将这些用户属性作为头部传递。

为了将属性作为环境变量传递(相当于 mod_shib 中的 ShibUseEnvironment On),必须使用 shib_request_set 指令手动提取每个属性。目前不能对所有属性进行 批量 提取,因为每个后端可能以不同的方式接受参数(fastcgi_paramuwsgi_param 等)。欢迎拉取请求以自动化此行为。

  • 如果授权器子请求返回 任何 其他状态(包括重定向或错误),则将授权器响应的状态和头部返回给客户端。

这意味着在 401 Unauthorized403 Forbidden 时,将拒绝访问,并将来自授权器的头部(例如 WWW-Authenticate)传递给客户端。所有其他授权器响应(例如 3xx 重定向)将返回给客户端,包括状态和头部,允许重定向到 WAYF 页面和 Shibboleth 响应器(Shibboleth.sso)正常工作。

FastCGI 授权器规范要求将响应体返回给客户端,但由于 Nginx 当前不支持缓冲子请求响应(NGX_HTTP_SUBREQUEST_IN_MEMORY),因此授权器响应体实际上被忽略。解决方法是让 Nginx 提供自己的 error_page,如下所示:

location /secure {
   shib_request /shibauthorizer;
   error_page 403 /shibboleth-forbidden.html;
   ...
}

如果 Shibboleth 授权器拒绝用户访问此位置,则会提供给定的错误页面。如果未指定 error_page,Nginx 将提供其通用错误页面。

请注意,这 适用于 Shibboleth 响应器(通常托管在 Shibboleth.sso),因为它是 FastCGI 响应器,Nginx 完全兼容,因为不使用子请求。

有关更多详细信息,请参见 https://forum.nginx.org/read.php?2,238444,238453

虽然此模块专门针对 Shibboleth 的 FastCGI 授权器,但它可能也适用于其他授权器,需考虑上述规范的偏差。

测试

每当对存储库进行新提交或打开新拉取请求时,测试将在 GitHub Actions 上自动运行(使用 此配置)。如果出现问题,您将收到通知,并且结果将在 GitHub 上报告。

测试使用简单的 Bash 脚本组合编写,用于编译我们的模块与不同版本和配置的 Nginx,以及用于集成测试的 Test::Nginx Perl 测试框架。有关如何扩展测试的信息,请查阅前面的链接,并参考底层的 Test::Base 文档,了解有关 blocks() 函数的内容。

集成测试由 CI 自动运行,但也可以手动运行(需要安装 Perl 和 CPAN):

cd nginx-http-shibboleth
cpanm --notest --local-lib=$HOME/perl5 Test::Nginx
## nginx 必须在 PATH 中并构建了调试符号
PERL5LIB=$HOME/perl5/lib/perl5 prove

帮助与支持

有关 Shibboleth 配置和 Nginx 或 Web 服务器设置的支持请求应直接发送到 Shibboleth 社区用户邮件列表。有关详细信息,请参见 https://www.shibboleth.net/community/lists/

调试

由于 nginx/FastCGI/Shibboleth 堆栈的复杂性,调试配置问题可能很困难。以下是一些关键点:

  1. 确认 nginx-http-shibboleth 已成功构建并安装在 nginx 中。您可以通过运行 nginx -V 并检查输出中的 --add-module=[path]/nginx-http-shibboleth--add-dynamic-module=[path]/nginx-http-shibboleth 来检查。

  2. 如果使用动态模块的 nginx,请确认您已使用 load_module 指令加载此模块。如果您忘记加载模块,使用 shib_request 和其他指令将失败。

  3. 如果使用的 nginx 版本与我们 测试的版本 不同,或者您使用其他第三方模块,则应运行上述测试套件以确认兼容性。如果任何测试失败,请检查您的配置或考虑更新您的 nginx 版本。

  4. Shibboleth 配置:检查您的 shibboleth2.xml 和相关配置,以确保您的主机、路径和属性被正确释放。一个 示例配置 可以帮助您识别配置 shibboleth2.xml 以与 FastCGI 授权器配合使用的关键“注意事项”。

  5. 应用程序级别:在您的代码中,始终从最简单的调试输出(例如打印请求环境)开始,然后逐步深入。如果您想创建一个基本的独立应用程序,请查看 wiki 上的 Bottle 配置。

  6. 调试模块内部:如果您仔细检查了上述所有内容,那么您还可以调试此模块本身的行为。您需要编译带有调试支持的 nginx(通过 ./auto/configure --with-debug ...),并在运行 nginx 时,最好能够在前台运行并启用调试日志。将以下内容添加到您的 nginx.conf 中:

    daemon off;
    error_log stderr debug;
    

    然后运行 nginx。启动 nginx 时,您应该看到包含 [debug] 的行,并且在您发出请求时,控制台日志将继续。如果没有发生这种情况,请检查您的 nginx 配置和编译过程。

    当您最终发出请求命中(或应该调用)shib_request 位置块时,您将在输出中看到类似以下的行:

    [debug] 1234#0: shib request handler
    [debug] 1234#0: shib request set variables
    [debug] 1234#0: shib request authorizer handler
    [debug] 1234#0: shib request authorizer allows access
    [debug] 1234#0: shib request authorizer copied header: "AUTH_TYPE: shibboleth"
    [debug] 1234#0: shib request authorizer copied header: "REMOTE_USER: [email protected]"
    ...
    

    如果您没有看到这些包含 shib request ... 的行,或者如果您看到 某些 行但没有看到头部/变量被复制的地方,请仔细检查您的 nginx 配置。如果您仍然没有进展,可以在源代码中添加自己的调试行(遵循此模块的示例),以最终确定出错的原因和时机。如果这样做,请记得在每次更改后重新编译 nginx 和/或 nginx-http-shibboleth

如果您认为在核心模块代码中发现了错误,请 创建一个问题

您还可以搜索现有问题,因为可能有人之前遇到过类似的问题。

GitHub

您可以在 nginx-module-shibboleth 的 GitHub 存储库 中找到有关此模块的其他配置提示和文档。