跳转至

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 指令与其他访问模块(如 access、auth_basic)结合使用。此模块也可以与 ngx_http_auth_request_module 一起编译,但在同一 location 块中使用这两个模块未经测试且不建议。

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

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

指令

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

shib_request \<uri>|off | 上下文: http、server、location
默认值: off

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

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

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

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

shib_request_set \<variable> \<value>
上下文: http、server、location
默认值: none

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

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

shib_request_use_headers on|off | 上下文: http、server、location
默认值: 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_param、scgi_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_shib 的 ShibUseHeaders On 的行为,该行为将这些用户属性作为头部传递。

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

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

这意味着在 401 Unauthorized 或 403 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: john.smith@example.com"
    ...
    

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

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

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

GitHub

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