GitLabトークンのトラブルシューティング
GitLabのトークンを使用する際に、以下の問題が発生する可能性があります。
期限切れのアクセストークン
既存のアクセストークンが使用中で、expires_at値に達すると、トークンは期限切れになり、次のようになります:
- 認証に使用できなくなります。
- UIに表示されません。
このトークンを使用して行われたリクエストは、401 Unauthorized応答を返します。同じIPアドレスから短期間に多数の認証されていないリクエストが送信されると、GitLab.comから403 Forbidden応答が返されます。
認証リクエストの制限の詳細については、Gitとコンテナレジストリの認証失敗を参照してください。
ログから期限切れのアクセストークンを特定する
前提要件:
これを行うには、次の手順に従います:
- 管理者であること。
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_idIDが12のアクセストークンが使用されたことを示します。
このトークンの詳細については、パーソナルアクセストークンを使用してください。を使用してトークンローテーションすることもできます。
期限切れのアクセストークンを置き換える
トークンを置き換えるには、次の手順を実行します:
- このトークンが以前に使用された可能性がある場所を確認し、トークンをまだ使用している可能性のある自動化から削除します。
- パーソナルアクセストークンの場合は、APIを使用して、最近期限切れになったトークンを一覧表示します。たとえば、
https://gitlab.com/api/v4/personal_access_tokensに移動し、特定のexpires_at日付のトークンを見つけます。 - プロジェクトアクセストークンの場合は、プロジェクトアクセストークンを使用して、最近期限切れになったトークンを一覧表示します。
- グループアクセストークンの場合は、グループアクセストークンを使用して、最近期限切れになったトークンを一覧表示します。
- パーソナルアクセストークンの場合は、APIを使用して、最近期限切れになったトークンを一覧表示します。たとえば、
- 新しいアクセストークンを作成します:
- パーソナルアクセストークンの場合は、UIまたはユーザートークンを使用します。
- プロジェクトアクセストークンの場合は、UIまたはプロジェクトアクセストークンを使用します。
- グループアクセストークンの場合は、UIまたはグループアクセストークンを使用します。
- 古いアクセストークンを新しいアクセストークンに置き換えます。このプロセスは、シークレットとして構成されている場合やアプリケーションに埋め込まれている場合など、トークンの使用方法によって異なります。このトークンから作成されたリクエストは、
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}"特定の日付に有効期限が切れるパーソナル、プロジェクト、およびグループアクセストークンを特定する
有効期限のないアクセストークンは無期限に有効であるため、アクセストークンが漏洩した場合、セキュリティリスクとなります。
このリスクを管理するために、GitLab 16.0以降にアップグレードすると、有効期限のないpersonal 、project 、またはgroupアクセストークンには、アップグレード日から1年後の有効期限が自動的に設定されます。
GitLab 17.3以降、既存のトークンに対するこの自動設定は元に戻され、新しいアクセストークンの有効期限の適用を無効にすることができます。
日付が変更されたためにトークンの有効期限がいつ切れるかわからない場合は、その日付にGitLabにサインインしようとすると、予期しない認証の失敗が発生する可能性があります。
このイシューを管理するには、GitLab 17.2以降にアップグレードする必要があります。これらのバージョンには、トークンの有効期限日付の分析、延長、または削除を支援するツールが含まれているためです。
ツールを実行できない場合は、GitLab Self-Managedインスタンスでスクリプトを実行して、次のいずれかのトークンを特定することもできます:
- 特定の日付に有効期限が切れます。
- 有効期限が設定されていません。
これらのスクリプトは、ターミナルウィンドウで次のいずれかで実行します:
- 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詳細については、インシデント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.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ブロックされたユーザーに属するトークンを削除するには、token.destroy!のすぐ下にif token.user.blocked?を追加します。ただし、このアクションでは監査イベントは作成されません。メソッドとは異なります。
特定の月に有効期限が切れるトークンを検索する
このスクリプトは、特定の月に有効期限が切れるトークンを検索します。インスタンスが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.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使用するには、次の手順に従います:
- ターミナルウィンドウで、
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.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