在使用极狐GitLab 令牌时,您可能会遇到以下问题。

过期的访问令牌

如果现有的访问令牌正在使用中并达到了 expires_at 的值,令牌会过期,并且:

  • 无法再用于身份验证。
  • 在用户界面中不可见。

使用此令牌进行的请求将返回 401 Unauthorized 响应。来自同一 IP 地址在短时间内发送的过多未经授权的请求,将导致 JihuLab.com 返回 403 Forbidden 响应。

有关身份验证请求限制的更多信息,请参阅 Git 和容器注册表身份验证失败禁令

从日志中识别过期的访问令牌

{{< history >}}

  • 在极狐GitLab 17.2 中引入。

{{< /history >}}

前提条件:

您必须:

  • 是一名管理员
  • 具有访问 api_json.log 文件的权限。

要识别由于过期的访问令牌而导致失败的 401 Unauthorized 请求,请使用 api_json.log 文件中的以下字段:

字段名称 描述
meta.auth_fail_reason 请求被拒绝的原因。可能的值:token_expiredtoken_revokedinsufficient_scopeimpersonation_disabled
meta.auth_fail_token_id 描述尝试使用的令牌类型和 ID 的字符串。

当用户尝试使用过期的令牌时,meta.auth_fail_reasontoken_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 旋转令牌

替换过期的访问令牌

要替换令牌:

  1. 检查此令牌可能以前使用过的位置,并将其从任何可能仍在使用该令牌的自动化中移除。
    • 对于个人访问令牌,使用 API 列出最近过期的令牌。例如,转到 https://jihulab.com/api/v4/personal_access_tokens,并找到具有特定 expires_at 日期的令牌。
    • 对于项目访问令牌,使用 项目访问令牌 API 列出最近过期的令牌。
    • 对于群组访问令牌,使用 群组访问令牌 API 列出最近过期的令牌。
  2. 创建一个新的访问令牌:
  3. 用新访问令牌替换旧访问令牌。此过程因您如何使用令牌而异,例如如果配置为密钥或嵌入应用程序中。从该令牌发出的请求不应再返回 401 响应。

延长令牌的有效期

使用此脚本延迟某些令牌的过期时间。

从极狐GitLab 16.0 开始,所有访问令牌都有一个到期日期。在您部署至少极狐GitLab 16.0 后,任何没有过期的访问令牌将在部署日期一年后过期。

如果这个日期临近,并且有尚未旋转的令牌,您可以使用此脚本来延迟过期,给用户更多时间来旋转他们的令牌。

为特定令牌延长有效期

此脚本延长在指定日期到期的所有令牌的有效期,包括:

  • 个人访问令牌
  • 群组访问令牌
  • 项目访问令牌

对于群组和项目访问令牌,此脚本仅在升级到极狐GitLab 16.0 或更高版本时自动设置了过期日期的情况下延长这些令牌的有效期。如果群组或项目访问令牌是在生成时设置了过期日期,或已旋转,则该令牌的有效性取决于对资源的有效成员资格,因此无法使用此脚本延长令牌的有效期。

要使用此脚本:

{{< tabs >}}

{{< tab title=”Rails console session” >}}

  1. 在终端窗口中,使用 sudo gitlab-rails console 启动一个 Rails 控制台会话。
  2. 粘贴下面整个 extend_expiring_tokens.rb 脚本。如果需要,将 expiring_date 更改为其他日期。
  3. Enter

{{< /tab >}}

{{< tab title=”Rails Runner” >}}

  1. 在终端窗口中,连接到您的实例。
  2. 复制下面整个 extend_expiring_tokens.rb 脚本,并将其保存为实例上的一个文件:
    • 命名为 extend_expiring_tokens.rb
    • 如果需要,将 expiring_date 更改为其他日期。
    • 文件必须对 git:git 可访问。
  3. 运行此命令,将 /path/to/extend_expiring_tokens.rb 更改为 extend_expiring_tokens.rb 文件的完整路径:

    sudo gitlab-rails runner /path/to/extend_expiring_tokens.rb
    

有关更多信息,请参阅 Rails Runner 故障排除部分

{{< /tab >}}

{{< /tabs >}}

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 或更高版本,因为这些版本包含一个工具,帮助分析、延长或删除令牌过期日期

如果您无法运行该工具,您还可以在极狐GitLab 私有化部署实例中运行脚本,以识别以下任一类型的令牌:

  • 在特定日期到期。
  • 没有到期日期。

您可以通过以下任一方式从终端窗口运行这些脚本:

根据您是否已升级到极狐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 >}}

{{< tab title=”Rails console session” >}}

  1. 在终端窗口中,连接到您的实例。
  2. 使用 sudo gitlab-rails console 启动一个 Rails 控制台会话。
  3. 根据需要,复制下面整个 expired_tokens.rbexpired_tokens_date_range.rb 脚本,并将其粘贴到控制台中。将 expires_at_date 更改为您的实例升级到极狐GitLab 16.0 一年后的日期。
  4. Enter

{{< /tab >}}

{{< tab title=”Rails Runner” >}}

  1. 在终端窗口中,连接到您的实例。
  2. 根据需要,复制下面整个 expired_tokens.rbexpired_tokens_date_range.rb 脚本,并将其保存为实例上的一个文件:
    • 命名为 expired_tokens.rb
    • expires_at_date 更改为您的实例升级到极狐GitLab 16.0 一年后的日期。
    • 文件必须对 git:git 可访问。
  3. 运行此命令,将路径更改为 expired_tokens.rb 文件的完整路径:

    sudo gitlab-rails runner /path/to/expired_tokens.rb
    

有关更多信息,请参阅 Rails Runner 故障排除部分

{{< /tab >}}

{{< /tabs >}}

expired_tokens.rb

此脚本要求您知道极狐GitLab 实例升级到极狐GitLab 16.0 的确切日期。

# 将此值更改为您的极狐GitLab 实例升级一年后的日期。

expires_at_date = "2024-05-22"

# 检查即将到期的个人访问令牌
PersonalAccessToken.owner_is_human.where(expires_at: expires_at_date).find_each do |token|
  if token.user.blocked?
    next
    # 从输出中隐藏不可用的被阻止的个人访问令牌
  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

# 检查即将到期的项目和群组访问令牌
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

{{< alert type=”note” >}}

如果不仅要隐藏,还要移除属于被阻止用户的令牌,请在 if token.user.blocked? 下面直接添加 token.destroy!。但是,与 API 方法 不同,此操作不会留下审计事件。

{{< /alert >}}

查找在特定月份到期的令牌

此脚本查找在特定月份到期的令牌。您无需知道实例升级到极狐GitLab 16.0 的确切日期。使用方法:

{{< tabs >}}

{{< tab title=”Rails console session” >}}

  1. 在终端窗口中,使用 sudo gitlab-rails console 启动一个 Rails 控制台会话。
  2. 粘贴下面整个 tokens_with_no_expiry.rb 脚本。如果需要,将 date_range 更改为其他范围。
  3. Enter

{{< /tab >}}

{{< tab title=”Rails Runner” >}}

  1. 在终端窗口中,连接到您的实例。
  2. 复制下面整个 tokens_with_no_expiry.rb 脚本,并将其保存为实例上的一个文件:
    • 命名为 expired_tokens_date_range.rb
    • 如果需要,将 date_range 更改为其他范围。
    • 文件必须对 git:git 可访问。
  3. 运行此命令,将 /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 故障排除部分

{{< /tab >}}

{{< /tabs >}}

expired_tokens_date_range.rb

# 此脚本允许您在当前日期起的特定日期范围内(例如 1 个月)搜索令牌。如果您不确定极狐GitLab 16.0 的升级确切完成时间,请使用它。

date_range = 1.month

# 检查个人访问令牌
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

# 检查即将到期的项目和群组访问令牌
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 >}}

{{< tab title=”Rails console session” >}}

  1. 在终端窗口中,使用 sudo gitlab-rails console 启动一个 Rails 控制台会话。
  2. 粘贴整个 dates_when_most_of_tokens_expire.rb 脚本。
  3. Enter

{{< /tab >}}

{{< tab title=”Rails Runner” >}}

  1. 在终端窗口中,连接到您的实例。
  2. 复制整个 dates_when_most_of_tokens_expire.rb 脚本,并将其保存为实例上的一个文件:
    • 命名为 dates_when_most_of_tokens_expire.rb
    • 文件必须对 git:git 可访问。
  3. 运行此命令,将 /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 故障排除部分

{{< /tab >}}

{{< /tabs >}}

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_atNULL。对于尚未升级到极狐GitLab 16.0 或更高版本的用户,令牌的 expires_at 值为 NULL,可以用于识别需要添加到期日期的令牌。

您可以在 Rails 控制台Rails Runner 中使用此脚本:

{{< tabs >}}

{{< tab title=”Rails console session” >}}

  1. 在终端窗口中,连接到您的实例。
  2. 使用 sudo gitlab-rails console 启动一个 Rails 控制台会话。
  3. 粘贴下面整个 tokens_with_no_expiry.rb 脚本。
  4. Enter

{{< /tab >}}

{{< tab title=”Rails Runner” >}}

  1. 在终端窗口中,连接到您的实例。
  2. 复制下面整个 tokens_with_no_expiry.rb 脚本,并将其保存为实例上的一个文件:
    • 命名为 tokens_with_no_expiry.rb
    • 文件必须对 git:git 可访问。
  3. 运行此命令,将路径更改为 tokens_with_no_expiry.rb 文件的完整路径:

    sudo gitlab-rails runner /path/to/tokens_with_no_expiry.rb
    

有关更多信息,请参阅 Rails Runner 故障排除部分

{{< /tab >}}

{{< /tabs >}}

tokens_with_no_expiry.rb

此脚本查找没有设置 expires_at 值的令牌。

# 此脚本查找没有设置 expires_at 值的令牌。

# 检查个人访问令牌
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

# 检查即将到期的项目和群组访问令牌
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