GitLab 토큰 문제 해결
Offering: GitLab Self-Managed, GitLab Dedicated
GitLab 토큰 작업 중 다음과 같은 문제가 발생할 수 있습니다. 기존 액세스 토큰이 사용 중이고 expires_at 값에 도달하면, 토큰이 만료되고: 이 토큰을 사용하여 만든 요청은 401 Unauthorized 응답을 반환합니다.
GitLab 토큰 작업 중 다음과 같은 문제가 발생할 수 있습니다.
만료된 액세스 토큰#
기존 액세스 토큰이 사용 중이고 expires_at 값에 도달하면, 토큰이 만료되고:
- 더 이상 인증에 사용할 수 없습니다.
- UI에서 표시되지 않습니다.
이 토큰을 사용하여 만든 요청은 401 Unauthorized 응답을 반환합니다. 동일한 IP 주소에서 짧은 시간 내에 너무 많은 승인되지 않은 요청이 발생하면 GitLab.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의 액세스 토큰이 사용되었음을 나타냅니다.
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 Runner 문제 해결 섹션을 참조하세요.
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 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 인스턴스에서 스크립트를 실행하여 다음 토큰을 식별할 수도 있습니다:
- 특정 날짜에 만료되는 토큰.
- 만료 날짜가 없는 토큰.
이러한 스크립트는 터미널 창에서 다음 중 하나를 통해 실행합니다:
- 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 Runner 문제 해결 섹션을 참조하세요.
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 Runner 문제 해결 섹션을 참조하세요.
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 Runner 문제 해결 섹션을 참조하세요.
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에서 실행할 수 있습니다:
- 터미널 창에서 인스턴스에 연결합니다.
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 Runner 문제 해결 섹션을 참조하세요.
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
