GitLabトークンのトラブルシューティング
GitLabのトークンを操作する際に、以下の問題が発生する可能性があります。
期限切れのアクセストークン
既存のアクセストークンが使用中でexpires_at値に達すると、トークンは期限切れとなり、以下のようになります:
- 認証に使用できなくなります。
- UIに表示されません。
このトークンを使用して行われたリクエストは、401 Unauthorizedレスポンスを返します。短期間に同じIPアドレスから大量の不正なリクエストが行われると、GitLab.comから403 Forbiddenレスポンスが返されます。
認証リクエストの制限に関する詳細については、Gitとコンテナレジストリの認証失敗によるBANを参照してください。
ログから期限切れのアクセストークンを特定する
前提条件:
これを行うには、次の手順に従います。
- 管理者である必要があります。
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のアクセストークンが使用されたことを示します。GitLab 18.9以降、失敗したリクエストに使用されたトークンに関連付けられたユーザー名もmeta.userに入力された状態になります。
このトークンに関する詳細情報を見つけるには、パーソナルアクセストークンAPIを使用してください。また、APIを使用してトークンをローテーションすることもできます。
期限切れのアクセストークンを置き換える
トークンを置き換えるには:
- このトークンが以前使用された可能性のある場所を確認し、まだトークンを使用している可能性のある自動化から削除します。
- パーソナルアクセストークンについては、APIを使用して最近期限切れになったトークンをリストします。たとえば、
https://gitlab.com/api/v4/personal_access_tokensにアクセスし、特定のexpires_at日付を持つトークンを見つけます。 - プロジェクトアクセストークンについては、プロジェクトアクセストークンAPIを使用して最近期限切れになったトークンをリストします。
- グループアクセストークンについては、グループアクセストークンAPIを使用して最近期限切れになったトークンをリストします。
- パーソナルアクセストークンについては、APIを使用して最近期限切れになったトークンをリストします。たとえば、
- 新しいアクセストークンを作成します:
- パーソナルアクセストークンについては、UIを使用するか、ユーザートークンAPIを使用します。
- プロジェクトアクセストークンについては、UIを使用するか、プロジェクトアクセストークンAPIを使用します。
- グループアクセストークンについては、UIを使用するか、グループアクセストークンAPIを使用します。
- 古いアクセストークンを新しいアクセストークンに置き換えます。このプロセスは、トークンの使用方法によって異なります。例えば、シークレットとして設定されている場合や、アプリケーションに組み込まれている場合などです。このトークンから行われたリクエストは、
401レスポンスを返すべきではありません。
トークンのライフタイムを延長する
このスクリプトを使用して、特定のトークンの有効期限を遅らせます。
GitLab 16.0以降、すべてのアクセストークンには有効期限があります。GitLab 16.0以降をデプロイすると、期限のないアクセストークンはデプロイ日から1年後に有効期限が切れます。
この日付が近づいていて、まだトークンローテーションされていないトークンがある場合、このスクリプトを使用して有効期限を遅らせ、ユーザーがトークンをローテーションする時間を増やすことができます。
特定のトークンのライフタイムを延長する
このスクリプトは、指定された日付に期限が切れるすべてのトークンのライフタイムを延長します。これには以下が含まれます:
- パーソナルアクセストークン
- グループアクセストークン
- プロジェクトアクセストークン
グループアクセストークンおよびプロジェクトアクセストークンの場合、このスクリプトは、GitLab 16.0以降にアップグレードする際に自動的に有効期限が設定された場合にのみ、これらのトークンのライフタイムを延長します。グループアクセストークンまたはプロジェクトアクセストークンが有効期限付きで生成された場合、またはローテーションされた場合、そのトークンの有効性はリソースへの有効なメンバーシップに依存するため、このスクリプトを使用してトークンのライフタイムを延長することはできません。
スクリプトを使用するには:
- ターミナルウィンドウで、
sudo gitlab-rails consoleを使用してRailsコンソールセッションを開始します。 - 以下のセクションから
extend_expiring_tokens.rbスクリプト全体を貼り付けます。必要に応じて、expiring_dateを別の日付に変更します。 - Enterキーを押します。
ターミナルウィンドウで、インスタンスに接続します。
以下のセクションから
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ランナーのトラブルシューティングセクションを参照してください。
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}"パーソナルアクセストークンを復元する
- プラン: Free、Premium、Ultimate
- 提供形態: GitLab Self-Managed、GitLab Dedicated
GitLab Self-ManagedインスタンスまたはGitLab Dedicatedインスタンスでは、管理者は誤って失効したパーソナルアクセストークンを復元することができます。GitLab.comでは、復元は利用できません。
以下のコマンドを実行すると、データが直接変更されます。正しく実行されなかったり、適切な条件下で実行されなかったりすると、問題を引き起こす可能性があります。念のため、まずはインスタンスのバックアップを準備したテスト環境でこれらのコマンドを実行してください。
Railsコンソールを開きます。
トークンを復元する:
token = PersonalAccessToken.find_by_token('<token_string>') token.update!(revoked:false)たとえば、
token-string-here123のトークンを復元するには:token = PersonalAccessToken.find_by_token('token-string-here123') token.update!(revoked:false)
特定の日付で期限切れになるパーソナルアクセストークン、プロジェクトアクセストークン、およびグループアクセストークンを特定する
有効期限のないアクセストークンは無期限に有効であるため、アクセストークンが漏洩した場合、セキュリティリスクとなります。
このリスクを管理するために、GitLab 16.0以降にアップグレードすると、パーソナル 、プロジェクト 、またはグループのアクセストークンで有効期限がないものは、自動的にアップグレード日から1年後に有効期限が設定されます。
GitLab 17.3以降では、既存のトークンに対するこの自動的な有効期限設定は元に戻され、新しいアクセストークンの有効期限の強制を無効にすることができます。
日付が変更されたため、トークンの有効期限がいつなのかがわからない場合、その日にGitLabにサインインしようとすると予期しない認証エラーが発生する可能性があります。
この問題を管理するには、GitLab 17.2以降にアップグレードする必要があります。これらのバージョンには、トークンの有効期限を分析、延長、または削除するのに役立つツールが含まれているためです。
ツールを実行できない場合は、GitLab Self-Managedインスタンスでスクリプトを実行して、以下のいずれかのトークンを特定することもできます:
- 特定の日付に期限が切れる。
- 有効期限がない。
これらのスクリプトは、ターミナルウィンドウから以下のいずれかで実行します:
- A Railsコンソールセッション。
- Railsランナーを使用します。
実行する特定のスクリプトは、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これに関する詳細については、インシデント18003を参照してください。
特定の日付に期限が切れるすべてのトークンを見つける
このスクリプトは、特定の日付に期限が切れるトークンを見つけます。
前提条件:
- お使いのインスタンスがGitLab 16.0にアップグレードされた正確な日付を知っている必要があります。
使用するには:
- ターミナルウィンドウで、インスタンスに接続します。
sudo gitlab-rails consoleを使用してRailsコンソールセッションを開始します。- 必要に応じて、以下のセクションの
expired_tokens.rb全体、またはその次のセクションのexpired_tokens_date_range.rbスクリプトをコピーしてコンソールに貼り付けます。expires_at_dateを、お使いのインスタンスがGitLab 16.0にアップグレードされた日から1年後の日付に変更します。 - Enterキーを押します。
ターミナルウィンドウで、インスタンスに接続します。
必要に応じて、以下のセクションの
expired_tokens.rb全体、またはその次のセクションのexpired_tokens_date_range.rbスクリプトをコピーし、インスタンス上のファイルとして保存します:- 名前を
expired_tokens.rbにします expires_at_dateを、お使いのインスタンスがGitLab 16.0にアップグレードされた日から1年後の日付に変更します。- このファイルは
git:gitがアクセスできる必要があります。
- 名前を
このコマンドを実行し、
expired_tokens.rbをファイルの完全なパスに変更します:sudo gitlab-rails runner /path/to/expired_tokens.rb
詳細については、Railsランナーのトラブルシューティングセクションを参照してください。
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.for_user_types(: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にアップグレードされた正確な日付を知る必要はありません。使用するには:
- ターミナルウィンドウで、
sudo gitlab-rails consoleを使用してRailsコンソールセッションを開始します。 - 次のセクションの
expired_tokens_date_range.rbスクリプト全体を貼り付けます。必要に応じて、date_rangeを別の範囲に変更します。 - Enterキーを押します。
ターミナルウィンドウで、インスタンスに接続します。
次のセクションの
expired_tokens_date_range.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ランナーのトラブルシューティングセクションを参照してください。
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.for_user_types(: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使用するには:
- ターミナルウィンドウで、
sudo gitlab-rails consoleを使用してRailsコンソールセッションを開始します。 - スクリプト
dates_when_most_of_tokens_expire.rb全体を貼り付けます。 - Enterキーを押します。
ターミナルウィンドウで、インスタンスに接続します。
この
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ランナーのトラブルシューティングセクションを参照してください。
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ランナーのいずれかで使用できます:
- ターミナルウィンドウで、インスタンスに接続します。
sudo gitlab-rails consoleを使用してRailsコンソールセッションを開始します。- 以下のセクションから
tokens_with_no_expiry.rbスクリプト全体を貼り付けます。 - Enterキーを押します。
ターミナルウィンドウで、インスタンスに接続します。
以下のセクションからこの
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ランナーのトラブルシューティングセクションを参照してください。
tokens_with_no_expiry.rb
このスクリプトは、expires_atに値が設定されていないトークンを見つけます。
# This script finds tokens which do not have an expires_at value set.
# Check for expiring personal access tokens
PersonalAccessToken.for_user_types(: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