极狐GitLab 令牌故障排查
当使用极狐GitLab 令牌时,您可能会遇到以下问题。
过期的访问令牌
如果既有的访问令牌在使用且已达到 expires_at
值,则令牌会过期且:
- 无法再用于身份验证。
- 在 UI 中不可见。
使用此令牌的请求会返回 401 Unauthorized
响应。在短时间内从同一 IP 地址发出的太多未经授权的请求,会导致来自 JihuLab.com 的 403 Forbidden
响应。
对于认证请求限制的更多详情,可查阅 Git 和容器仓库失败身份验证禁用。
从日志中识别过期的访问令牌
- 引入于极狐GitLab 17.2。
先决条件:
您必须
- 是管理员。
- 能访问
api_json.log
文件。
要识别哪个 401 Unauthorized
请求失败是因为访问令牌过期导致,在 api_json.log
文件中使用以下字段:
字段名称 | 描述 |
---|---|
meta.auth_fail_reason |
请求被拒绝的原因。可能的值为: token_expired 、token_revoked 、insufficient_scope 和 impersonation_disabled 。 |
meta.auth_fail_token_id |
描述尝试令牌类型和 ID 的字符串。 |
当用户尝试使用过期令牌时,meta.auth_fail_reason
为 token_expired
。以下显示了日志条目的摘录:
{
"status": 401,
"method": "GET",
"path": "/api/v4/user",
...
"meta.auth_fail_reason": "token_expired",
"meta.auth_fail_token_id": "PersonalAccessToken/12",
}
meta.auth_fail_token_id
表明已使用 ID 为 12 的访问令牌。
要想找到与此令牌相关的更多信息,请使用个人访问令牌 API。您还可以使用 API 来 轮换令牌。
替代过期访问令牌
要替代过期令牌:
- 检查此令牌之前可能已用于何处,然后从任何可能仍在使用令牌的自动化中删除它。
- 对于个人访问令牌,使用 API 列出最近过期的令牌。例如,转到
https://jihulab.com/api/v4/personal_access_tokens
,并定位具有特定expires_at
日期的令牌。 - 对于项目访问令牌,使用 项目访问令牌 API 列出最近过期的令牌。
- 对于群组访问令牌,使用 群组访问令牌 API 列出最近过期的令牌。
- 对于个人访问令牌,使用 API 列出最近过期的令牌。例如,转到
- 创建新访问令牌:
- 对于个人访问令牌,使用 UI 或 用户令牌 API。
- 对于项目访问令牌,使用 UI 或 项目访问令牌 API。
- 对于群组访问令牌,使用 UI 或 群组访问令牌 API。
- 用新访问令牌替代旧访问令牌。此过程取决于您如何使用令牌,例如如果配置为密钥或嵌入应用程序中。从此令牌发出的请求不应再返回
401
响应。
扩展令牌生命周期
使用此脚本延迟某些令牌的生命周期。
从极狐GitLab 16.0 开始,所有访问令牌都有一个过期日期。在部署至少极狐GitLab 16.0 版本后,任何未过期的访问令牌将在部署日期一年后过期。
如果这个日期临近,且还有令牌尚未轮换,您可以使用此脚本延迟过期时间,并给用户更多时间来轮换他们的令牌。
扩展特定令牌的生命周期
此脚本会扩展在指定日期过期的所有令牌的生命周期,包括:
- 个人访问令牌
- 群组访问令牌
- 项目访问令牌
对于群组和项目访问令牌,此脚本仅在升级到极狐GitLab 16.0 或更高版本时自动为这些令牌分配过期日期时,才会延长这些令牌的生命周期。如果群组或项目访问令牌具有过期日期,或者已轮换,则该令牌的有效性取决于对资源的有效成员身份,因此使用此脚本无法延长该令牌的生命周期。
要使用脚本:
::Tabs
:::TabTitle Rails 控制台会话
- 在您的终端窗口,使用
sudo gitlab-rails console
启动 Rails 控制台回环。 - 请将整个
extend_expiring_tokens.rb
脚本粘贴到下面。如果想要,可以将expiring_date
更改为其他日期。 - 按 Enter。
:::TabTitle Rails Runner
- 在您的终端窗口,连接到您的实例。
- 将整个
extend_expiring_tokens.rb
脚本粘贴到下面,且将其保存为实例上的文件:- 名称为
extend_expiring_tokens.rb
。 - 如果需要,可以将
expiring_date
更改为其他日期。 - 该文件必须可被
git:git
访问。
- 名称为
-
运行此命令,将
/path/to/extend_expiring_tokens.rb
更改为extend_expiring_tokens.rb
文件的 完整 路径:sudo gitlab-rails runner /path/to/extend_expiring_tokens.rb
更多详情,请查阅 Rails Runner 故障排查部分。
::EndTabs
extend_expiring_tokens.rb
expiring_date = Date.new(2024, 5, 30)
new_expires_at = 6.months.from_now
total_updated = PersonalAccessToken
.not_revoked
.without_impersonation
.where(expires_at: expiring_date.to_date)
.update_all(expires_at: new_expires_at.to_date)
puts "Updated #{total_updated} tokens with new expiry date #{new_expires_at}"
识别个人、项目和群组访问令牌在特定日期过期
没有过期日期的访问令牌会无限期有效,如果访问令牌被泄露,这会带来安全风险。
要管理此风险,当您升级到 GitLab 16.0 及更高版本时,任何个人、项目或组访问令牌如果没有到期日期,自动在升级日期一年后设置到期日期。
在极狐GitLab 17.3 及以后,此自动设置过期日期的现有令牌已被撤销,您可以禁用对新访问令牌的到期日期强制执行。
如果您不知道令牌何时过期,因为日期已经更改,那么在该日期尝试登录极狐GitLab 时,可能会出现意外的身份验证失败。
要管理此议题,您应该升级到极狐GitLab 17.2 或更高版本,因为这些版本包含一个可帮助您分析延长或删除令牌过期日期的工具。
如果您无法运行工具,您可以在私有化部署实例上运行脚本来识别令牌:
- 在特定日期过期。
- 没有到期日期。
您可以采用如下方式在您的终端窗口上运行这些脚本:
- Rails 控制台会话。
- 使用 Rails Runner。
您要运行的脚本取决于您是否已升级到极狐GitLab 16.0 或更高版本,或没有:
- 如果您还没有升级到极狐GitLab 16.0 或更高版本,那么您可以使用脚本来识别没有到期日期的令牌。
- 如果您已经升级到极狐GitLab 16.0 或更高版本,您可以使用脚本来识别:
在您是被受此问题影响的令牌,您可以运行最终脚本来延长特定令牌的生命周期(如果需要)。
此脚本会以如下格式返回结果:
Expired group access token in Group ID 25, Token ID: 8, Name: Example Token, Scopes: ["read_api", "create_runner"], Last used:
Expired project access token in Project ID 2, Token ID: 9, Name: Test Token, Scopes: ["api", "read_registry", "write_registry"], Last used: 2022-02-11 13:22:14 UTC
找到所有特定日期过期的令牌
此脚本会找到在特定日期过期的令牌。
先决条件:
- 您必须知道您的实例升级到极狐GitLab 16.0 的确切日期。
要使用它:
::Tabs
:::TabTitle Rails 控制台会话
- 在您的终端窗口,连接到您的实例。
- 使用
sudo gitlab-rails console
启动 Rails 控制台会话。 - 根据您的需要,复制整个
expired_tokens.rb
或expired_tokens_date_range.rb
脚本,然后将其粘贴到控制台中。修改expires_at_date
为您的实例升级到极狐GitLab 16.0 一年后的日期。 - 按 Enter。
:::TabTitle Rails Runner
- 在您的终端窗口,连接到您的实例。
- 根据您的需要,复制下面的
expired_tokens.rb
或expired_tokens_date_range.rb
脚本,将其作为文件保存到实例上:- 将它命名为
expired_tokens.rb
。 - 将
expires_at_date
更改为您的实例升级到极狐GitLab 16.0 一年后的日期。 - 文件必须可被
git:git
访问。
- 将它命名为
-
运行此命令,将路径更改为
expired_tokens.rb
文件的 完整 路径:sudo gitlab-rails runner /path/to/expired_tokens.rb
更多详情,请查阅 Rails Runner 故障排查部分。
::EndTabs
expired_tokens.rb
此脚本需要您知道您的极狐GitLab 实例升级到极狐GitLab 16.0 的确切日期。
# Change this value to the date one year after your GitLab instance was upgraded.
expires_at_date = "2024-05-22"
# Check for expiring personal access tokens
PersonalAccessToken.owner_is_human.where(expires_at: expires_at_date).find_each do |token|
if token.user.blocked?
next
# Hide unusable, blocked PATs from output
end
puts "Expired personal access token ID: #{token.id}, User Email: #{token.user.email}, Name: #{token.name}, Scopes: #{token.scopes}, Last used: #{token.last_used_at}"
end
# Check for expiring project and group access tokens
PersonalAccessToken.project_access_token.where(expires_at: expires_at_date).find_each do |token|
token.user.members.each do |member|
type = member.is_a?(GroupMember) ? 'Group' : 'Project'
puts "Expired #{type} access token in #{type} ID #{member.source_id}, Token ID: #{token.id}, Name: #{token.name}, Scopes: #{token.scopes}, Last used: #{token.last_used_at}"
end
end
if token.user.blocked?
下直接添加 token.destroy!
。然而,这种方法不会留下审计事件,这一点与 API 方法不同。找到特定月份过期的令牌
此脚本会找到在特定月份过期的令牌。您不需要知道您的实例何时升级到 GitLab 16.0。要使用它:
::Tabs
:::TabTitle Rails 控制台会话
- 在您的终端窗口中,使用
sudo gitlab-rails console
启动 Rails 控制台会话。 - 将整个
tokens_with_no_expiry.rb
脚本粘贴到控制台中。如果想要,可以将date_range
更改为不同的范围。 - 按下 Enter。
:::TabTitle Rails Runner
- 在您的终端窗口中,连接到您的实例。
- 将整个
tokens_with_no_expiry.rb
脚本粘贴到控制台中并将其保存为实例上的文件:- 将它命名为
expired_tokens_date_range.rb
。 - 如果需要,将
date_range
更改为不同的范围。 - 该文件必须对
git:git
可访问。
- 将它命名为
-
运行此命令,将
/path/to/expired_tokens_date_range.rb
更改为expired_tokens_date_range.rb
的 完整 路径:sudo gitlab-rails runner /path/to/expired_tokens_date_range.rb
更多详情,请参阅 Rails Runner 故障排除部分。
::EndTabs
expired_tokens_date_range.rb
# This script enables you to search for tokens that expire within a
# certain date range (like 1.month) from the current date. Use it if
# you're unsure when exactly your GitLab 16.0 upgrade completed.
date_range = 1.month
# Check for personal access tokens
PersonalAccessToken.owner_is_human.where(expires_at: Date.today .. Date.today + date_range).find_each do |token|
puts "Expired personal access token ID: #{token.id}, User Email: #{token.user.email}, Name: #{token.name}, Scopes: #{token.scopes}, Last used: #{token.last_used_at}"
end
# Check for expiring project and group access tokens
PersonalAccessToken.project_access_token.where(expires_at: Date.today .. Date.today + date_range).find_each do |token|
token.user.members.each do |member|
type = member.is_a?(GroupMember) ? 'Group' : 'Project'
puts "Expired #{type} access token in #{type} ID #{member.source_id}, Token ID: #{token.id}, Name: #{token.name}, Scopes: #{token.scopes}, Last used: #{token.last_used_at}"
end
end
但大量令牌过期时识别过期日期
此脚本用于识别大量令牌过期的日期。您可以将其与本页上的其他脚本结合使用,以识别和扩展可能接近到期日期的大量令牌,以防您的团队尚未设置令牌轮换。
脚本以如下格式返回结果:
42 Personal access tokens will expire at 2024-06-27
17 Personal access tokens will expire at 2024-09-23
3 Personal access tokens will expire at 2024-08-13
要使用它:
::Tabs
:::TabTitle Rails 控制台会话
- 在您的终端窗口中,使用
sudo gitlab-rails console
启动 Rails 控制台会话。 - 将整个
dates_when_most_of_tokens_expire.rb
脚本粘贴到其中。 - 按 Enter。
:::TabTitle Rails Runner
- 在您的终端窗口中,连接到您的实例。
- 复制整个
dates_when_most_of_tokens_expire.rb
脚本,并将其保存为实例上的文件:- 将其命名为
dates_when_most_of_tokens_expire.rb
。 - 文件必须可由
git:git
访问。
- 将其命名为
-
运行此命令,将
/path/to/dates_when_most_of_tokens_expire.rb
更改为dates_when_most_of_tokens_expire.rb
文件的 完整 路径:sudo gitlab-rails runner /path/to/dates_when_most_of_tokens_expire.rb
更多详情,可查阅 Rails Runner 故障排除部分。
::EndTabs
dates_when_most_of_tokens_expire.rb
PersonalAccessToken
.select(:expires_at, Arel.sql('count(*)'))
.where('expires_at >= NOW()')
.group(:expires_at)
.order(Arel.sql('count(*) DESC'))
.limit(10)
.each do |token|
puts "#{token.count} Personal access tokens will expire at #{token.expires_at}"
end
找到没有过期日期的令牌
此脚本会查找没有过期日期的令牌:expires_at
为 NULL
。对于尚未升级到极狐GitLab 16.0 或更高版本的用户,令牌 expires_at
的值为 NULL
,可以用来识别需要添加过期日期的令牌。
您还可以在 Rails 控制台或 Rails Runner 中使用此脚本:
::Tabs
:::TabTitle Rails 控制台会话
- 在您的终端窗口中,连接到您的实例。
- 使用
sudo gitlab-rails console
启动 Rails 控制台会话。 - 粘贴整个
tokens_with_no_expiry.rb
脚本。 - 按 Enter。
:::TabTitle Rails Runner
- 在您的终端窗口中,连接到您的实例。
- 复制整个
tokens_with_no_expiry.rb
脚本,并将其保存为实例上的文件:- 将其命名为
tokens_with_no_expiry.rb
。 - 该文件必须可被
git:git
访问。
- 将其命名为
-
运行此命令,将路径更改为
tokens_with_no_expiry.rb
文件的 完整 路径:sudo gitlab-rails runner /path/to/tokens_with_no_expiry.rb
更多详情,请参阅 Rails Runner 故障排除部分。
::EndTabs
tokens_with_no_expiry.rb
This script finds tokens without a value set for expires_at
.
# This script finds tokens which do not have an expires_at value set.
# Check for expiring personal access tokens
PersonalAccessToken.owner_is_human.where(expires_at: nil).find_each do |token|
puts "Expires_at is nil for personal access token ID: #{token.id}, User Email: #{token.user.email}, Name: #{token.name}, Scopes: #{token.scopes}, Last used: #{token.last_used_at}"
end
# Check for expiring project and group access tokens
PersonalAccessToken.project_access_token.where(expires_at: nil).find_each do |token|
token.user.members.each do |member|
type = member.is_a?(GroupMember) ? 'Group' : 'Project'
puts "Expires_at is nil for #{type} access token in #{type} ID #{member.source_id}, Token ID: #{token.id}, Name: #{token.name}, Scopes: #{token.scopes}, Last used: #{token.last_used_at}"
end
end