InfoGrab DocsInfoGrab Docs

LDAP 문제 해결

요약

관리자인 경우, 다음 정보를 사용하여 LDAP 문제를 해결하세요. LDAP 서버에 연결할 때 Connection Refused 오류 메시지가 표시되면, GitLab에서 사용하는 LDAP port 및 encryption 설정을 검토하세요.

관리자인 경우, 다음 정보를 사용하여 LDAP 문제를 해결하세요.

일반적인 문제 및 워크플로#

연결#

연결 거부#

LDAP 서버에 연결할 때 Connection Refused 오류 메시지가 표시되면, GitLab에서 사용하는 LDAP portencryption 설정을 검토하세요. 일반적인 조합은 encryption: 'plain'port: 389, 또는 encryption: 'simple_tls'port: 636입니다.

연결 시간 초과#

GitLab이 LDAP 엔드포인트에 연결할 수 없는 경우, 다음과 같은 메시지가 표시됩니다:

Could not authenticate you from Ldapmain because "Connection timed out - user specified timeout".

설정된 LDAP 공급자 및/또는 엔드포인트가 오프라인이거나 GitLab에서 연결할 수 없는 경우, 어떤 LDAP 사용자도 인증하거나 로그인할 수 없습니다. GitLab은 LDAP 중단 시 인증을 제공하기 위해 LDAP 사용자의 자격 증명을 캐시하거나 저장하지 않습니다.

이 오류가 표시되면 LDAP 공급자 또는 관리자에게 문의하세요.

참조 오류#

로그에서 LDAP search error: Referral이 표시되거나 LDAP 그룹 동기화를 문제 해결할 때 이 오류가 표시되면, 설정 문제를 나타낼 수 있습니다. LDAP 설정 파일 /etc/gitlab/gitlab.rb(Omnibus) 또는 config/gitlab.yml(source)은 YAML 형식이며 들여쓰기에 민감합니다. group_baseadmin_group 설정 키가 서버 식별자 뒤에 공백 2개로 들여쓰여 있는지 확인하세요. 기본 식별자는 main이며, 예시 스니펫은 다음과 같습니다:

main: # 'main' is the GitLab 'provider ID' of this LDAP server
  label: 'LDAP'
  host: 'ldap.example.com'
  # ...
  group_base: 'cn=my_group,ou=groups,dc=example,dc=com'
  admin_group: 'my_admin_group'

LDAP 쿼리#

다음은 Rails 콘솔을 사용하여 LDAP에서 검색을 수행할 수 있게 해줍니다. 수행하려는 작업에 따라 사용자그룹을 직접 쿼리하거나, ldapsearch를 사용하는 것이 더 적합할 수도 있습니다.

adapter = Gitlab::Auth::Ldap::Adapter.new('ldapmain')
options = {
    # :base is required
    # use .base or .group_base
    base: adapter.config.group_base,

    # :filter is optional
    # 'cn' looks for all "cn"s under :base
    # '*' is the search string - here, it's a wildcard
    filter: Net::LDAP::Filter.eq('cn', '*'),

    # :attributes is optional
    # the attributes we want to get returned
    attributes: %w(dn cn memberuid member submember uniquemember memberof)
}
adapter.ldap_search(options)

필터에서 OID를 사용할 때는 Net::LDAP::Filter.eqNet::LDAP::Filter.construct로 교체하세요:

adapter = Gitlab::Auth::Ldap::Adapter.new('ldapmain')
options = {
    # :base is required
    # use .base or .group_base
    base: adapter.config.base,

    # :filter is optional
    # This filter includes OID 1.2.840.113556.1.4.1941
    # It will search for all direct and nested members of the group gitlab_grp in the LDAP directory
    filter: Net::LDAP::Filter.construct("(memberOf:1.2.840.113556.1.4.1941:=CN=gitlab_grp,DC=example,DC=com)"),

    # :attributes is optional
    # the attributes we want to get returned
    attributes: %w(dn cn memberuid member submember uniquemember memberof)
}
adapter.ldap_search(options)

실행 방법의 예시는 Adapter 모듈 검토를 참조하세요.

사용자 로그인#

사용자를 찾을 수 없음#

LDAP에 연결할 수 있음을 확인했지만 GitLab이 출력에 LDAP 사용자를 표시하지 않는 경우, 다음 중 하나가 해당될 가능성이 높습니다:

  • bind_dn 사용자에게 사용자 트리를 탐색할 충분한 권한이 없습니다.

  • 사용자가 설정된 base 아래에 속하지 않습니다.

  • 설정된 user_filter가 사용자에 대한 접근을 차단하고 있습니다.

이 경우, /etc/gitlab/gitlab.rb의 기존 LDAP 설정을 사용하여 ldapsearch로 이전 내용 중 어느 것이 사실인지 확인할 수 있습니다.

사용자가 로그인할 수 없음#

사용자는 여러 가지 이유로 로그인에 어려움을 겪을 수 있습니다. 시작하기 위해 스스로에게 다음과 같은 질문을 해보세요:

  • 사용자가 LDAP에서 설정된 base 아래에 속하나요? 사용자는 이 base 아래에 속해야 로그인할 수 있습니다.

  • 사용자가 설정된 user_filter를 통과하나요? 설정되지 않은 경우 이 질문은 무시할 수 있습니다. 설정된 경우, 사용자는 로그인이 허용되려면 이 필터도 통과해야 합니다.

user_filter 디버깅에 대한 문서를 참조하세요.

이전 질문이 모두 괜찮은 경우, 다음으로 살펴볼 곳은 문제를 재현하는 동안 로그 자체입니다.

  • 사용자에게 로그인을 요청하고 실패하도록 두세요.

  • 로그인에 관한 오류나 기타 메시지를 출력에서 확인하세요. 이 페이지의 다른 오류 메시지 중 하나가 표시될 수 있으며, 해당 섹션에서 문제를 해결하는 데 도움이 됩니다.

로그에서 문제의 근본 원인을 찾을 수 없는 경우, Rails 콘솔을 사용하여 이 사용자를 쿼리하여 GitLab이 LDAP 서버에서 이 사용자를 읽을 수 있는지 확인하세요.

추가 조사를 위해 사용자 동기화 디버깅도 도움이 될 수 있습니다.

사용자에게 "잘못된 로그인 또는 비밀번호" 오류가 표시됨#

히스토리

사용자에게 이 오류가 표시되는 경우, Standard 로그인 양식 대신 LDAP 로그인 양식을 사용하여 로그인을 시도하기 때문일 수 있습니다.

해결하려면, 사용자에게 LDAP 로그인 양식에 LDAP 사용자 이름과 비밀번호를 입력하도록 요청하세요.

로그인 시 잘못된 자격 증명#

사용된 로그인 자격 증명이 LDAP에서 정확하다면, 해당 사용자에 대해 다음이 사실인지 확인하세요:

  • 바인딩에 사용하는 사용자가 사용자의 트리를 읽고 탐색하기에 충분한 권한이 있는지 확인하세요.

  • user_filter가 그렇지 않으면 유효한 사용자를 차단하지 않는지 확인하세요.

  • LDAP 확인 명령을 실행하여 LDAP 설정이 올바른지, GitLab에서 사용자를 볼 수 있는지 확인하세요.

LDAP 계정에 대한 접근이 거부됨#

버그Auditor 수준 접근을 가진 사용자에게 영향을 줄 수 있습니다. Premium/Ultimate에서 다운그레이드할 때, 로그인을 시도하는 Auditor 사용자는 다음 메시지를 볼 수 있습니다: Access denied for your LDAP account.

해결 방법은 영향을 받은 사용자의 접근 수준을 변경하는 것입니다.

사전 요구 사항:

  • 관리자 접근 권한.

  • 오른쪽 상단 모서리에서 Admin을 선택하세요.

  • 왼쪽 사이드바에서 Overview > Users를 선택하세요.

  • 영향을 받은 사용자의 이름을 선택하세요.

  • 오른쪽 상단 모서리에서 Edit를 선택하세요.

  • 사용자의 접근 수준을 Regular에서 Administrator로 변경하세요(또는 그 반대로).

  • 페이지 하단에서 Save changes를 선택하세요.

  • 오른쪽 상단 모서리에서 다시 Edit를 선택하세요.

  • 사용자의 원래 접근 수준(Regular 또는 Administrator)을 복원하고 다시 Save changes를 선택하세요.

이제 사용자가 로그인할 수 있어야 합니다.

이메일이 이미 사용 중#

사용자가 올바른 LDAP 자격 증명으로 로그인을 시도하지만 접근이 거부되며, production.log에 다음과 같은 오류가 표시됩니다:

(LDAP) Error saving user  (email@example.com): ["Email has already been taken"]

이 오류는 LDAP의 이메일 주소 email@example.com을 참조합니다. GitLab에서 이메일 주소는 고유해야 하며, LDAP은 사용자의 기본 이메일(수많은 보조 이메일 중 하나가 아닌)에 연결됩니다. 다른 사용자(또는 동일한 사용자)가 보조 이메일로 email@example.com을 설정했기 때문에 이 오류가 발생합니다.

Rails 콘솔을 사용하여 이 충돌하는 이메일 주소의 출처를 확인할 수 있습니다. 콘솔에서 다음을 실행하세요:

# This searches for an email among the primary AND secondary emails
user = User.find_by_any_email('email@example.com')
user.username

이렇게 하면 어느 사용자가 이 이메일 주소를 가지고 있는지 알 수 있습니다. 여기에서 두 가지 단계 중 하나를 취해야 합니다:

  • LDAP으로 로그인할 때 이 사용자를 위한 새 GitLab 사용자/사용자 이름을 생성하려면, 충돌을 제거하기 위해 보조 이메일을 제거하세요.

  • 이 사용자가 LDAP과 함께 사용할 기존 GitLab 사용자/사용자 이름을 사용하려면, 이 이메일을 보조 이메일에서 제거하고 기본 이메일로 설정하여 GitLab이 이 프로필을 LDAP 신원과 연결하도록 하세요.

사용자는 프로필에서 이러한 단계 중 하나를 수행하거나 관리자가 수행할 수 있습니다.

프로젝트 제한 오류#

다음 오류는 제한 또는 제약이 활성화되어 있지만 관련 데이터 필드에 데이터가 없음을 나타냅니다:

  • Projects limit can't be blank.

  • Projects limit is not a number.

이를 해결하려면:

  • 오른쪽 상단 모서리에서 Admin을 선택하세요.

  • 왼쪽 사이드바에서 Settings > General을 선택하세요.

  • 다음 항목 모두를 확장하세요:

Account and limit.

  • New user account restrictions.

  • 예를 들어 Default projects limit 또는 Allowed domains for new user accounts 필드를 확인하고 관련 값이 설정되어 있는지 확인하세요.

LDAP 사용자 필터 디버깅#

ldapsearch를 사용하면 설정된 사용자 필터를 테스트하여 예상하는 사용자가 반환되는지 확인할 수 있습니다.

ldapsearch -H ldaps://$host:$port -D "$bind_dn" -y bind_dn_password.txt  -b "$base" "$user_filter" sAMAccountName
  • $로 시작하는 변수는 설정 파일의 LDAP 섹션에 있는 변수를 참조합니다.

  • 일반 인증 방법을 사용하는 경우 ldaps://ldap://로 교체하세요. 포트 389는 기본 ldap:// 포트이며, 636은 기본 ldaps:// 포트입니다.

  • bind_dn 사용자의 비밀번호가 bind_dn_password.txt에 있다고 가정합니다.

모든 사용자 동기화#

수동 사용자 동기화의 출력은 GitLab이 LDAP에 대해 사용자를 동기화하려고 할 때 어떤 일이 발생하는지 보여줄 수 있습니다. Rails 콘솔에 접속한 다음 실행하세요:

Rails.logger.level = Logger::DEBUG

LdapSyncWorker.new.perform

다음으로, 출력을 읽는 방법을 알아보세요.

사용자 동기화 후 콘솔 출력 예시#

수동 사용자 동기화의 출력은 매우 상세하며, 단일 사용자의 성공적인 동기화는 다음과 같을 수 있습니다:

Syncing user John, email@example.com
  Identity Load (0.9ms)  SELECT  "identities".* FROM "identities" WHERE "identities"."user_id" = 20 AND (provider LIKE 'ldap%') LIMIT 1
Instantiating Gitlab::Auth::Ldap::Person with LDIF:
dn: cn=John Smith,ou=people,dc=example,dc=com
cn: John Smith
mail: email@example.com
memberof: cn=admin_staff,ou=people,dc=example,dc=com
uid: John

  UserSyncedAttributesMetadata Load (0.9ms)  SELECT  "user_synced_attributes_metadata".* FROM "user_synced_attributes_metadata" WHERE "user_synced_attributes_metadata"."user_id" = 20 LIMIT 1
   (0.3ms)  BEGIN
  Namespace Load (1.0ms)  SELECT  "namespaces".* FROM "namespaces" WHERE "namespaces"."owner_id" = 20 AND "namespaces"."type" IS NULL LIMIT 1
  Route Load (0.8ms)  SELECT  "routes".* FROM "routes" WHERE "routes"."source_id" = 27 AND "routes"."source_type" = 'Namespace' LIMIT 1
  Ci::Runner Load (1.1ms)  SELECT "ci_runners".* FROM "ci_runners" INNER JOIN "ci_runner_namespaces" ON "ci_runners"."id" = "ci_runner_namespaces"."runner_id" WHERE "ci_runner_namespaces"."namespace_id" = 27
   (0.7ms)  COMMIT
   (0.4ms)  BEGIN
  Route Load (0.8ms)  SELECT "routes".* FROM "routes" WHERE (LOWER("routes"."path") = LOWER('John'))
  Namespace Load (1.0ms)  SELECT  "namespaces".* FROM "namespaces" WHERE "namespaces"."id" = 27 LIMIT 1
  Route Exists (0.9ms)  SELECT  1 AS one FROM "routes" WHERE LOWER("routes"."path") = LOWER('John') AND "routes"."id" != 50 LIMIT 1
  User Update (1.1ms)  UPDATE "users" SET "updated_at" = '2019-10-17 14:40:59.751685', "last_credential_check_at" = '2019-10-17 14:40:59.738714' WHERE "users"."id" = 20

여기에는 많은 내용이 있으므로, 디버깅 시 도움이 될 수 있는 내용을 살펴보겠습니다.

먼저, GitLab은 이전에 LDAP으로 로그인한 모든 사용자를 찾아 이들을 순회합니다. 각 사용자의 동기화는 현재 GitLab에 존재하는 사용자의 사용자 이름과 이메일이 포함된 다음 줄로 시작합니다:

Syncing user John, email@example.com

특정 사용자의 GitLab 이메일이 출력에 없는 경우, 해당 사용자는 아직 LDAP으로 로그인하지 않은 것입니다.

다음으로, GitLab은 이 사용자와 설정된 LDAP 공급자 사이의 기존 연결을 위해 identities 테이블을 검색합니다:

  Identity Load (0.9ms)  SELECT  "identities".* FROM "identities" WHERE "identities"."user_id" = 20 AND (provider LIKE 'ldap%') LIMIT 1

신원 객체에는 GitLab이 LDAP에서 사용자를 검색하는 데 사용하는 DN이 있습니다. DN이 없으면 대신 이메일을 사용합니다. 이 사용자가 LDAP에서 발견되었음을 알 수 있습니다:

Instantiating Gitlab::Auth::Ldap::Person with LDIF:
dn: cn=John Smith,ou=people,dc=example,dc=com
cn: John Smith
mail: email@example.com
memberof: cn=admin_staff,ou=people,dc=example,dc=com
uid: John

DN 또는 이메일로 사용자가 LDAP에서 발견되지 않으면, 다음 메시지가 대신 표시될 수 있습니다:

LDAP search error: No Such Object

이 경우 사용자가 차단됩니다:

  User Update (0.4ms)  UPDATE "users" SET "state" = $1, "updated_at" = $2 WHERE "users"."id" = $3  [["state", "ldap_blocked"], ["updated_at", "2019-10-18 15:46:22.902177"], ["id", 20]]

LDAP에서 사용자가 발견된 후, 나머지 출력은 변경 사항이 있으면 GitLab 데이터베이스를 업데이트합니다.

LDAP에서 사용자 쿼리#

이를 통해 GitLab이 LDAP에 연결하여 특정 사용자를 읽을 수 있는지 테스트합니다. GitLab UI에서 자동으로 실패하는 것처럼 보이는 LDAP 연결 및/또는 쿼리 오류를 노출할 수 있습니다.

Rails.logger.level = Logger::DEBUG

adapter = Gitlab::Auth::Ldap::Adapter.new('ldapmain') # If `main` is the LDAP provider
Gitlab::Auth::Ldap::Person.find_by_uid('<uid>', adapter)

머지 리퀘스트 승인 규칙#

LDAP 연결 문제가 발생하면, 동기화 작업 중에 사용자가 머지 리퀘스트 승인 규칙에서 제거될 수 있습니다. 이로 인해 승인 규칙이 비워지고 유효하지 않은 것으로 표시될 수 있습니다.

LDAP 연결이 끊어질 때 승인 규칙 실패#

LDAP 서버가 일시적으로 사용 불가능하거나 바인드 계정이 실패하는 경우:

  • LDAP 기반 승인 규칙에 설정된 사용자가 다음 동기화 주기 중에 제거될 수 있습니다.

  • 남은 사용자가 없는 승인 규칙은 유효하지 않은 것으로 표시됩니다.

  • 표준 승인 규칙은 Auto approved로 표시되며 더 이상 머지를 차단하지 않습니다.

  • 머지 리퀘스트 승인 정책 규칙은 Action required로 표시되며 계속 머지를 차단합니다.

표준 승인 규칙이 자동으로 우회되는 것을 방지하려면:

  • LDAP 서버가 고가용성과 안정적인 연결성을 갖추도록 하세요.

  • LDAP 동기화 작업의 실패를 모니터링하세요.

  • 중요한 보안 요구 사항에는 표준 승인 규칙 대신 머지 리퀘스트 승인 정책을 사용하세요. 승인 정책은 더 강력한 적용을 제공하며 자동으로 실패하지 않습니다.

승인 규칙 동작에 대한 자세한 내용은 유효하지 않은 규칙을 참조하세요.

LDAP 문제로 인해 사용자가 승인 규칙에서 제거되면 LDAP 연결이 복원되어도 자동으로 다시 추가되지 않습니다. 승인 규칙을 수동으로 복원하거나 백업에서 복구해야 할 수 있습니다.

그룹 멤버십#

멤버십이 부여되지 않음#

때로는 특정 사용자가 LDAP 그룹 동기화를 통해 GitLab 그룹에 추가되어야 한다고 생각하지만, 어떤 이유로 그렇게 되지 않을 수 있습니다. 상황을 디버깅하기 위해 여러 가지를 확인할 수 있습니다.

  • LDAP 설정에 group_base가 지정되어 있는지 확인하세요. 이 설정은 그룹 동기화가 제대로 작동하기 위해 필요합니다.

  • 올바른 LDAP 그룹 링크가 GitLab 그룹에 추가되어 있는지 확인하세요.

  • 사용자에게 LDAP 신원이 있는지 확인하세요:

관리자 사용자로 GitLab에 로그인하세요.

  • 오른쪽 상단 모서리에서 Admin을 선택하세요.

  • 왼쪽 사이드바에서 Overview > Users를 선택하세요.

  • 사용자를 검색하세요.

  • 사용자의 이름을 선택하여 열어보세요. Edit는 선택하지 마세요.

  • Identities 탭을 선택하세요. Identifier로 LDAP DN이 있는 LDAP 신원이 있어야 합니다. 없다면, 이 사용자는 아직 LDAP으로 로그인하지 않았으므로 먼저 로그인해야 합니다.

  • 그룹이 동기화되도록 한 시간 또는 설정된 간격을 기다렸습니다. 프로세스를 빠르게 진행하려면, GitLab 그룹 Manage > Members로 이동하여 Sync now(한 그룹 동기화)를 누르거나 그룹 동기화 Rake 태스크를 실행(모든 그룹 동기화)하세요.

모든 확인이 양호한 경우, Rails 콘솔에서 좀 더 고급 디버깅을 진행하세요.

  • Rails 콘솔에 접속하세요.

  • 테스트할 GitLab 그룹을 선택하세요. 이 그룹에는 이미 LDAP 그룹 링크가 설정되어 있어야 합니다.

  • 디버그 로깅을 활성화하고, 선택된 GitLab 그룹을 찾아 LDAP와 동기화하세요.

  • 동기화 출력을 살펴보세요. 출력을 읽는 방법은 예시 로그 출력을 참조하세요.

  • 사용자가 추가되지 않는 이유를 여전히 알 수 없는 경우, LDAP 그룹을 직접 쿼리하여 어떤 멤버가 나열되어 있는지 확인하세요.

  • 쿼리된 그룹의 목록 중 하나에 사용자의 DN 또는 UID가 있나요? 여기의 DN 또는 UID 중 하나는 앞서 확인한 LDAP 신원의 'Identifier'와 일치해야 합니다. 일치하지 않으면 사용자가 LDAP 그룹에 없는 것으로 보입니다.

LDAP 동기화가 활성화된 경우 서비스 계정 사용자를 그룹에 추가할 수 없음#

그룹에 LDAP 동기화가 활성화된 경우, "invite" 대화 상자를 사용하여 새 그룹 멤버를 초대할 수 없습니다.

GitLab 16.8 이상에서 이 문제를 해결하려면, 그룹 멤버 API 엔드포인트를 사용하여 서비스 계정을 그룹에 초대하거나 제거할 수 있습니다.

관리자 권한이 부여되지 않음#

LDAP 그룹에 관리자 권한을 할당했지만 설정된 사용자에게 올바른 관리자 권한이 부여되지 않는 경우, 다음 조건이 사실인지 확인하세요:

  • group_base가 설정되어 있는지 확인하세요.

  • gitlab.rb의 설정된 admin_group이 DN이나 배열이 아닌 CN인지 확인하세요.

  • 이 CN이 설정된 group_base의 범위 내에 있는지 확인하세요.

  • admin_group의 멤버가 이미 LDAP 자격 증명으로 GitLab에 로그인했는지 확인하세요. GitLab은 LDAP에 이미 연결된 계정을 가진 사용자에게만 관리자 접근을 부여합니다.

이전 조건이 모두 사실이고 사용자가 여전히 접근 권한을 얻지 못하는 경우, Rails 콘솔에서 수동 그룹 동기화를 실행하고 출력을 살펴보아 GitLab이 admin_group을 동기화할 때 어떤 일이 발생하는지 확인하세요.

UI에서 Sync now 버튼이 멈춤#

그룹의 Group > Members 페이지에 있는 Sync now 버튼이 멈출 수 있습니다. 버튼이 눌리고 페이지가 새로 고쳐진 후 멈추게 됩니다. 그러면 버튼을 다시 선택할 수 없습니다.

Sync now 버튼은 여러 가지 이유로 멈출 수 있으며 특정 케이스에 대한 디버깅이 필요합니다. 다음은 두 가지 가능한 원인과 문제에 대한 가능한 해결책입니다.

유효하지 않은 멤버십#

Sync now 버튼은 그룹의 멤버 또는 요청 멤버 중 일부가 유효하지 않은 경우 멈춥니다. 이 문제의 가시성을 개선하는 진행 상황은 관련 이슈에서 확인할 수 있습니다. Rails 콘솔을 사용하여 이 문제가 Sync now 버튼이 멈추는 원인인지 확인할 수 있습니다:

# Find the group in question
group = Group.find_by(name: 'my_gitlab_group')

# Look for errors on the Group itself
group.valid?
group.errors.map(&:full_messages)

# Look for errors among the group's members and requesters
group.requesters.map(&:valid?)
group.requesters.map(&:errors).map(&:full_messages)
group.members.map(&:valid?)
group.members.map(&:errors).map(&:full_messages)

표시된 오류는 문제를 식별하고 해결책을 제시할 수 있습니다. 예를 들어, 지원 팀에서는 다음 오류를 확인했습니다:

irb(main):018:0> group.members.map(&:errors).map(&:full_messages)
=> [["The member's email address is not allowed for this group. Go to the group's 'Settings > General' page, and check 'Restrict membership by email domain'."]]

이 오류는 관리자가 이메일 도메인으로 그룹 멤버십을 제한하도록 선택했지만, 도메인에 오타가 있음을 보여주었습니다. 도메인 설정이 수정된 후, Sync now 버튼이 다시 정상적으로 작동했습니다.

Sidekiq 노드에 LDAP 설정이 없음#

GitLab이 여러 노드로 확장되어 있고 Sidekiq를 실행하는 노드의 /etc/gitlab/gitlab.rb에 LDAP 설정이 없는 경우, Sync now 버튼이 멈춥니다. 이 경우, Sidekiq 작업이 사라지는 것처럼 보입니다.

Sidekiq 노드에 LDAP가 필요한 이유는 LDAP에 로컬 LDAP 설정이 필요한 비동기적으로 실행되는 여러 작업이 있기 때문입니다:

Sidekiq를 실행하는 각 노드에서 LDAP를 확인하는 Rake 태스크를 실행하여 LDAP 설정 누락이 문제인지 테스트할 수 있습니다. LDAP가 이 노드에 올바르게 설정되어 있으면 LDAP 서버에 연결하고 사용자를 반환합니다.

이 문제를 해결하려면, Sidekiq 노드에 LDAP를 설정하세요. 설정 후, LDAP를 확인하는 Rake 태스크를 실행하여 GitLab 노드가 LDAP에 연결할 수 있는지 확인하세요.

모든 그룹 동기화#

디버깅이 필요하지 않을 때 모든 그룹을 수동으로 동기화하려면, Rake 태스크를 사용하세요.

수동 그룹 동기화의 출력은 GitLab이 LDAP 그룹 멤버십을 LDAP에 대해 동기화할 때 어떤 일이 발생하는지 보여줄 수 있습니다. Rails 콘솔에 접속한 다음 실행하세요:

Rails.logger.level = Logger::DEBUG

LdapAllGroupsSyncWorker.new.perform

다음으로, 출력을 읽는 방법을 알아보세요.

그룹 동기화 후 콘솔 출력 예시#

사용자 동기화 출력과 마찬가지로, 수동 그룹 동기화의 출력도 매우 상세합니다. 그러나 많은 유용한 정보가 포함되어 있습니다.

동기화가 실제로 시작되는 지점을 나타냅니다:

Started syncing 'ldapmain' provider for 'my_group' group

다음 항목은 GitLab이 LDAP 서버에서 볼 수 있는 모든 사용자 DN의 배열을 보여줍니다. 이 DN들은 GitLab 그룹이 아닌 단일 LDAP 그룹의 사용자입니다. 이 GitLab 그룹에 여러 LDAP 그룹이 연결되어 있는 경우, 이와 같은 여러 로그 항목(각 LDAP 그룹당 하나)이 표시됩니다. 이 로그 항목에서 LDAP 사용자 DN이 보이지 않으면, 조회를 할 때 LDAP에서 해당 사용자를 반환하지 않는 것입니다. 사용자가 실제로 LDAP 그룹에 있는지 확인하세요.

Members in 'ldap_group_1' LDAP group: ["uid=john0,ou=people,dc=example,dc=com",
"uid=mary0,ou=people,dc=example,dc=com", "uid=john1,ou=people,dc=example,dc=com",
"uid=mary1,ou=people,dc=example,dc=com", "uid=john2,ou=people,dc=example,dc=com",
"uid=mary2,ou=people,dc=example,dc=com", "uid=john3,ou=people,dc=example,dc=com",
"uid=mary3,ou=people,dc=example,dc=com", "uid=john4,ou=people,dc=example,dc=com",
"uid=mary4,ou=people,dc=example,dc=com"]

각 항목 직후에 해결된 멤버 접근 수준의 해시가 표시됩니다. 이 해시는 GitLab이 이 그룹에 접근 권한이 있어야 한다고 생각하는 모든 사용자 DN과 접근 수준(권한)을 나타냅니다. 이 해시는 누적되며, 추가 LDAP 그룹 조회를 기반으로 더 많은 DN이 추가되거나 기존 항목이 수정될 수 있습니다. 이 항목의 마지막 발생은 GitLab이 그룹에 추가해야 한다고 생각하는 사용자를 정확히 나타냅니다.

10은 Guest, 20은 Reporter, 25는 Security Manager, 30은 Developer, 40은 Maintainer, 50은 Owner입니다.

Resolved 'my_group' group member access: {"uid=john0,ou=people,dc=example,dc=com"=>30,
"uid=mary0,ou=people,dc=example,dc=com"=>30, "uid=john1,ou=people,dc=example,dc=com"=>30,
"uid=mary1,ou=people,dc=example,dc=com"=>30, "uid=john2,ou=people,dc=example,dc=com"=>30,
"uid=mary2,ou=people,dc=example,dc=com"=>30, "uid=john3,ou=people,dc=example,dc=com"=>30,
"uid=mary3,ou=people,dc=example,dc=com"=>30, "uid=john4,ou=people,dc=example,dc=com"=>30,
"uid=mary4,ou=people,dc=example,dc=com"=>30}

다음과 같은 경고가 표시되는 것은 드문 일이 아닙니다. 이는 GitLab이 사용자를 그룹에 추가했을 것이지만 사용자가 GitLab에서 찾을 수 없음을 나타냅니다. 일반적으로 이것은 걱정할 필요가 없습니다.

특정 사용자가 이미 GitLab에 존재해야 한다고 생각하지만 이 항목이 표시되는 경우, GitLab에 저장된 DN이 일치하지 않기 때문일 수 있습니다. 사용자의 LDAP 신원을 업데이트하려면 사용자 DN 및 이메일이 변경됨을 참조하세요.

User with DN `uid=john0,ou=people,dc=example,dc=com` should have access
to 'my_group' group but there is no user in GitLab with that
identity. Membership will be updated when the user signs in for
the first time.

마지막으로, 다음 항목은 이 그룹의 동기화가 완료되었음을 나타냅니다:

Finished syncing all providers for 'my_group' group

설정된 모든 그룹 링크가 동기화된 후, GitLab은 동기화할 관리자 또는 외부 사용자를 찾습니다:

Syncing admin users for 'ldapmain' provider

출력은 단일 그룹과 유사하게 보이며, 이 줄은 동기화가 완료되었음을 나타냅니다:

Finished syncing admin users for 'ldapmain' provider

관리자 권한을 할당하지 않은 경우, 이 메시지가 표시됩니다:

No `admin_group` configured for 'ldapmain' provider. Skipping

하나의 그룹 동기화#

모든 그룹 동기화는 단일 GitLab 그룹의 멤버십만 문제 해결하려는 경우 산만할 수 있는 많은 출력을 생성할 수 있습니다. 이 경우, 이 그룹만 동기화하고 디버그 출력을 보는 방법은 다음과 같습니다:

Rails.logger.level = Logger::DEBUG

# Find the GitLab group.
# If the output is `nil`, the group could not be found.
# If a bunch of group attributes are in the output, your group was found successfully.
group = Group.find_by(name: 'my_gitlab_group')

# Sync this group against LDAP
EE::Gitlab::Auth::Ldap::Sync::Group.execute_all_providers(group)

출력은 모든 그룹 동기화에서 얻는 출력과 유사합니다.

LDAP에서 그룹 쿼리#

GitLab이 LDAP 그룹을 읽고 모든 멤버를 볼 수 있는지 확인하려면, 다음을 실행할 수 있습니다:

# Find the adapter and the group itself
adapter = Gitlab::Auth::Ldap::Adapter.new('ldapmain') # If `main` is the LDAP provider
ldap_group = EE::Gitlab::Auth::Ldap::Group.find_by_cn('group_cn_here', adapter)

# Find the members of the LDAP group
ldap_group.member_dns
ldap_group.member_uids

LDAP 동기화가 그룹에서 그룹 생성자를 제거하지 않음#

LDAP 동기화는 LDAP 그룹에 해당 사용자가 존재하지 않는 경우, LDAP 그룹의 생성자를 그룹에서 제거해야 합니다. LDAP 동기화를 실행해도 이 작업이 수행되지 않는 경우:

  • LDAP 그룹에 사용자를 추가하세요.

  • LDAP 그룹 동기화가 실행이 완료될 때까지 기다리세요.

  • LDAP 그룹에서 사용자를 제거하세요.

사용자 DN 및 이메일이 변경됨#

LDAP에서 기본 이메일과 DN이 모두 변경된 경우, GitLab은 사용자의 올바른 LDAP 레코드를 식별할 수 없습니다. 결과적으로 GitLab은 해당 사용자를 차단합니다. GitLab이 LDAP 레코드를 찾을 수 있도록, 사용자의 기존 GitLab 프로필을 다음 중 최소 하나 이상으로 업데이트하세요:

  • 새 기본 이메일.

  • DN 값.

다음 스크립트는 제공된 모든 사용자의 이메일을 업데이트하여 차단되거나 계정에 접근할 수 없게 되는 일이 없도록 합니다.

다음 스크립트를 사용하기 전에 새 이메일 주소를 가진 새 계정이 먼저 제거되어야 합니다. GitLab에서 이메일 주소는 고유해야 합니다.

Rails 콘솔로 이동한 다음 실행하세요:

# Each entry must include the old username and the new email
emails = {
  'ORIGINAL_USERNAME' => 'NEW_EMAIL_ADDRESS',
  ...
}

emails.each do |username, email|
  user = User.find_by_username(username)
  user.email = email
  user.skip_reconfirmation!
  user.save!
end

그런 다음 UserSync를 실행하여 이 사용자들 각각에 대한 최신 DN을 동기화할 수 있습니다.

AzureActivedirectoryV2에서 Invalid grant로 인해 인증할 수 없음#

LDAP에서 SAML로 변환할 때 Azure에서 다음과 같은 오류가 발생할 수 있습니다:

Authentication failure! invalid_credentials: OAuth2::Error, invalid_grant.

이 문제는 다음 조건이 모두 해당할 때 발생합니다:

  • SAML이 해당 사용자에게 설정된 후에도 LDAP 신원이 여전히 존재합니다.

  • 해당 사용자에 대해 LDAP를 비활성화했습니다.

로그에 LDAP와 Azure 메타데이터가 모두 포함되어 Azure에서 오류가 생성됩니다.

단일 사용자에 대한 해결 방법은 Admin > Identities에서 사용자의 LDAP 신원을 제거하는 것입니다.

여러 LDAP 신원을 제거하려면, 아래 Could not authenticate you from Ldapmain because "Unknown provider" 오류에 대한 해결 방법 중 하나를 사용하세요.

오류: Ldapmain에서 "Unknown provider"로 인해 인증할 수 없음#

LDAP 서버로 인증할 때 다음 오류가 발생할 수 있습니다:

Could not authenticate you from Ldapmain because "Unknown provider (ldapsecondary). available providers: ["ldapmain"]".

이 오류는 이름이 변경되거나 GitLab 설정에서 제거된 LDAP 서버로 이전에 인증한 계정을 사용할 때 발생합니다. 예를 들어:

  • 처음에는 GitLab 설정의 ldap_serversmainsecondary가 설정되어 있습니다.

  • secondary 설정이 제거되거나 main으로 이름이 변경됩니다.

  • 로그인을 시도하는 사용자가 secondary에 대한 identify 레코드를 가지고 있지만, 더 이상 설정되어 있지 않습니다.

Rails 콘솔을 사용하여 영향을 받은 사용자를 나열하고 어떤 LDAP 서버에 대한 신원이 있는지 확인하세요:

ldap_identities = Identity.where(provider: "ldapsecondary")
ldap_identities.each do |identity|
  u=User.find_by_id(identity.user_id)
  ui=Identity.where(user_id: identity.user_id)
  puts "user: #{u.username}\n   #{u.email}\n   last activity: #{u.last_activity_on}\n   #{identity.provider} ID: #{identity.id} external: #{identity.extern_uid}"
  puts "   all identities:"
  ui.each do |alli|
    puts "    - #{alli.provider} ID: #{alli.id} external: #{alli.extern_uid}"
  end
end;nil

이 오류는 두 가지 방법으로 해결할 수 있습니다.

LDAP 서버에 대한 참조 이름 변경#

이 해결 방법은 LDAP 서버가 서로의 복제본이고, 영향을 받은 사용자가 설정된 LDAP 서버를 사용하여 로그인할 수 있어야 하는 경우에 적합합니다. 예를 들어, 이제 로드 밸런서를 사용하여 LDAP 고가용성을 관리하고 별도의 보조 로그인 옵션이 더 이상 필요하지 않은 경우입니다.

LDAP 서버가 서로의 복제본이 아닌 경우, 이 해결 방법은 영향을 받은 사용자가 로그인할 수 없게 합니다.

더 이상 설정되지 않은 LDAP 서버에 대한 참조 이름을 변경하려면 실행하세요:

sudo gitlab-rake gitlab:ldap:rename_provider[ldapsecondary,ldapmain]

제거된 LDAP 서버와 관련된 신원 레코드 제거#

사전 요구 사항:

  • auto_link_ldap_user가 활성화되어 있는지 확인하세요.

이 해결 방법을 사용하면, 신원이 삭제된 후 영향을 받은 사용자가 설정된 LDAP 서버로 로그인할 수 있으며 GitLab에서 새로운 identity 레코드가 생성됩니다.

제거된 LDAP 서버가 ldapsecondary이므로, Rails 콘솔에서 모든 ldapsecondary 신원을 삭제하세요:

ldap_identities = Identity.where(provider: "ldapsecondary")
ldap_identities.each do |identity|
  puts "Destroying identity: #{identity.id} #{identity.provider}: #{identity.extern_uid}"
  identity.destroy!
rescue => e
  puts 'Error generated when destroying identity:\n ' + e.to_s
end; nil

만료된 라이선스로 인해 여러 LDAP 서버에서 오류 발생#

여러 LDAP 서버를 사용하려면 유효한 라이선스가 필요합니다. 만료된 라이선스는 다음을 유발할 수 있습니다:

  • 웹 인터페이스에서 502 오류.

  • 로그의 다음 오류(실제 전략 이름은 /etc/gitlab/gitlab.rb에 설정된 이름에 따라 다름):

Could not find a strategy with name `Ldapsecondary'. Please ensure it is required or explicitly set it using the :strategy_class option. (Devise::OmniAuth::StrategyNotFound)

이 오류를 해결하려면, 웹 인터페이스 없이 GitLab 인스턴스에 새 라이선스를 적용해야 합니다:

사용자가 그룹에서 제거되고 다시 추가됨#

사용자가 그룹 동기화 중에 그룹에 추가되었다가 다음 동기화 시 제거되는 일이 반복된다면, 사용자에게 여러 개 또는 중복된 LDAP 신원이 없는지 확인하세요.

이러한 신원 중 하나가 더 이상 사용하지 않는 이전 LDAP 공급자에 대해 추가된 경우, 제거된 LDAP 서버와 관련된 identity 레코드를 제거하세요.

디버깅 도구#

LDAP 확인#

LDAP를 확인하는 Rake 태스크는 GitLab이 LDAP에 성공적으로 연결을 설정하고 사용자를 읽을 수 있는지 확인하는 데 도움이 되는 유용한 도구입니다.

연결을 설정할 수 없는 경우, 설정 문제나 방화벽이 연결을 차단하고 있기 때문일 가능성이 높습니다.

  • 방화벽이 연결을 차단하지 않는지, LDAP 서버가 GitLab 호스트에서 접근 가능한지 확인하세요.

  • Rake 확인 출력에서 오류 메시지를 찾아보세요. 이는 LDAP 설정(특히 host, port, bind_dn, password)이 올바른지 확인하는 데 도움이 됩니다.

  • 연결 실패를 더 디버깅하려면 로그에서 오류를 찾아보세요.

GitLab이 LDAP에 성공적으로 연결할 수 있지만 사용자를 반환하지 않으면, 사용자를 찾을 수 없을 때 해야 할 일을 참조하세요.

GitLab 로그#

LDAP 설정으로 인해 사용자 계정이 차단되거나 차단 해제되면, application_json.log에 메시지가 기록됩니다.

LDAP 조회 중에 예기치 않은 오류(설정 오류, 시간 초과)가 발생하면, 로그인이 거부되고 production.log에 메시지가 기록됩니다.

ldapsearch#

ldapsearch는 LDAP 서버를 쿼리할 수 있는 유틸리티입니다. LDAP 설정을 테스트하고 사용 중인 설정이 원하는 결과를 제공하는지 확인하는 데 사용할 수 있습니다.

ldapsearch를 사용할 때, gitlab.rb 설정에 이미 지정한 것과 동일한 설정을 사용하여 정확한 설정을 사용할 때 어떤 일이 발생하는지 확인하세요.

GitLab 호스트에서 이 명령을 실행하면 GitLab 호스트와 LDAP 사이에 장애물이 없는지도 확인하는 데 도움이 됩니다.

예를 들어, 다음 GitLab 설정을 고려하세요:

gitlab_rails['ldap_servers'] = YAML.load <<-'EOS' # remember to close this block with 'EOS' below
   main: # 'main' is the GitLab 'provider ID' of this LDAP server
     label: 'LDAP'
     host: '127.0.0.1'
     port: 389
     uid: 'uid'
     encryption: 'plain'
     bind_dn: 'cn=admin,dc=ldap-testing,dc=example,dc=com'
     password: 'Password1'
     active_directory: true
     allow_username_or_email_login: false
     block_auto_created_users: false
     base: 'dc=ldap-testing,dc=example,dc=com'
     user_filter: ''
     attributes:
       username: ['uid', 'userid', 'sAMAccountName']
       email:    ['mail', 'email', 'userPrincipalName']
       name:       'cn'
       first_name: 'givenName'
       last_name:  'sn'
     group_base: 'ou=groups,dc=ldap-testing,dc=example,dc=com'
     admin_group: 'gitlab_admin'
EOS

bind_dn 사용자를 찾기 위해 다음 ldapsearch를 실행하세요:

ldapsearch -D "cn=admin,dc=ldap-testing,dc=example,dc=com" \
  -w Password1 \
  -p 389 \
  -h 127.0.0.1 \
  -b "dc=ldap-testing,dc=example,dc=com"

bind_dn, password, port, host, base는 모두 gitlab.rb에 설정된 것과 동일합니다.

start_tls 암호화로 ldapsearch 사용#

이전 예시는 포트 389에 평문으로 LDAP 테스트를 수행합니다. start_tls 암호화를 사용하는 경우, ldapsearch 명령에 다음을 포함하세요:

  • -Z 플래그.

  • LDAP 서버의 FQDN.

TLS 협상 중에 LDAP 서버의 FQDN이 인증서와 대조되어 평가되기 때문에 이를 포함해야 합니다:

ldapsearch -D "cn=admin,dc=ldap-testing,dc=example,dc=com" \
  -w Password1 \
  -p 389 \
  -h "testing.ldap.com" \
  -b "dc=ldap-testing,dc=example,dc=com" -Z

simple_tls 암호화로 ldapsearch 사용#

simple_tls 암호화(일반적으로 포트 636)를 사용하는 경우, ldapsearch 명령에 다음을 포함하세요:

  • -H 플래그와 포트를 사용한 LDAP 서버 FQDN.

  • 완전히 구성된 URI.

ldapsearch -D "cn=admin,dc=ldap-testing,dc=example,dc=com" \
  -w Password1 \
  -H "ldaps://testing.ldap.com:636" \
  -b "dc=ldap-testing,dc=example,dc=com"

자세한 내용은 공식 ldapsearch 문서를 참조하세요.

AdFind 사용 (Windows)#

AdFind 유틸리티(Windows 기반 시스템에서)를 사용하여 LDAP 서버에 접근 가능하고 인증이 올바르게 작동하는지 테스트할 수 있습니다. AdFind은 Joe Richards가 만든 프리웨어 유틸리티입니다.

모든 객체 반환

objectclass=* 필터를 사용하여 모든 디렉터리 객체를 반환할 수 있습니다.

adfind -h ad.example.org:636 -ssl -u "CN=GitLabSRV,CN=Users,DC=GitLab,DC=org" -up Password1 -b "OU=GitLab INT,DC=GitLab,DC=org" -f (objectClass=*)

필터를 사용하여 단일 객체 반환

객체 이름이나 전체 DN지정하여 단일 객체를 검색할 수도 있습니다. 이 예시에서는 객체 이름 CN=Leroy Fox만 지정합니다.

adfind -h ad.example.org:636 -ssl -u "CN=GitLabSRV,CN=Users,DC=GitLab,DC=org" -up Password1 -b "OU=GitLab INT,DC=GitLab,DC=org" -f "(&(objectcategory=person)(CN=Leroy Fox))"

Rails 콘솔#

Rails 콘솔로 데이터를 생성, 읽기, 수정, 삭제하는 것은 매우 쉽습니다. 명령을 정확하게 나열된 대로 실행하세요.

Rails 콘솔은 LDAP 문제를 디버깅하는 데 도움이 되는 유용한 도구입니다. 명령을 실행하고 GitLab이 이에 어떻게 응답하는지 확인하여 애플리케이션과 직접 상호 작용할 수 있습니다.

Rails 콘솔 사용 방법에 대한 지침은 이 가이드를 참조하세요.

디버그 출력 활성화#

이것은 GitLab이 무엇을 하고 있으며 무엇으로 하고 있는지 보여주는 디버그 출력을 제공합니다. 이 값은 지속되지 않으며, Rails 콘솔의 이 세션에서만 활성화됩니다.

Rails 콘솔에서 디버그 출력을 활성화하려면, Rails 콘솔에 접속하고 실행하세요:

Rails.logger.level = Logger::DEBUG

그룹, 하위 그룹, 멤버 및 요청자와 관련된 모든 오류 메시지 가져오기#

그룹, 하위 그룹, 멤버 및 요청자와 관련된 오류 메시지를 수집하세요. 이는 웹 인터페이스에 표시되지 않을 수 있는 오류 메시지를 캡처합니다. LDAP 그룹 동기화 문제 해결과 그룹 및 하위 그룹의 사용자 및 멤버십과 관련된 예기치 않은 동작에 특히 도움이 될 수 있습니다.

# Find the group and subgroup
group = Group.find_by_full_path("parent_group")
subgroup = Group.find_by_full_path("parent_group/child_group")

# Group and subgroup errors
group.valid?
group.errors.map(&:full_messages)

subgroup.valid?
subgroup.errors.map(&:full_messages)

# Group and subgroup errors for the members AND requesters
group.requesters.map(&:valid?)
group.requesters.map(&:errors).map(&:full_messages)
group.members.map(&:valid?)
group.members.map(&:errors).map(&:full_messages)
group.members_and_requesters.map(&:errors).map(&:full_messages)

subgroup.requesters.map(&:valid?)
subgroup.requesters.map(&:errors).map(&:full_messages)
subgroup.members.map(&:valid?)
subgroup.members.map(&:errors).map(&:full_messages)
subgroup.members_and_requesters.map(&:errors).map(&:full_messages)

LDAP 문제 해결

GitLab v19.2
Tier: Premium, Ultimate
Offering: GitLab Self-Managed
원문 보기
요약

관리자인 경우, 다음 정보를 사용하여 LDAP 문제를 해결하세요. LDAP 서버에 연결할 때 Connection Refused 오류 메시지가 표시되면, GitLab에서 사용하는 LDAP port 및 encryption 설정을 검토하세요.

관리자인 경우, 다음 정보를 사용하여 LDAP 문제를 해결하세요.

일반적인 문제 및 워크플로#

연결#

연결 거부#

LDAP 서버에 연결할 때 Connection Refused 오류 메시지가 표시되면, GitLab에서 사용하는 LDAP portencryption 설정을 검토하세요. 일반적인 조합은 encryption: 'plain'port: 389, 또는 encryption: 'simple_tls'port: 636입니다.

연결 시간 초과#

GitLab이 LDAP 엔드포인트에 연결할 수 없는 경우, 다음과 같은 메시지가 표시됩니다:

Could not authenticate you from Ldapmain because "Connection timed out - user specified timeout".

설정된 LDAP 공급자 및/또는 엔드포인트가 오프라인이거나 GitLab에서 연결할 수 없는 경우, 어떤 LDAP 사용자도 인증하거나 로그인할 수 없습니다. GitLab은 LDAP 중단 시 인증을 제공하기 위해 LDAP 사용자의 자격 증명을 캐시하거나 저장하지 않습니다.

이 오류가 표시되면 LDAP 공급자 또는 관리자에게 문의하세요.

참조 오류#

로그에서 LDAP search error: Referral이 표시되거나 LDAP 그룹 동기화를 문제 해결할 때 이 오류가 표시되면, 설정 문제를 나타낼 수 있습니다. LDAP 설정 파일 /etc/gitlab/gitlab.rb(Omnibus) 또는 config/gitlab.yml(source)은 YAML 형식이며 들여쓰기에 민감합니다. group_baseadmin_group 설정 키가 서버 식별자 뒤에 공백 2개로 들여쓰여 있는지 확인하세요. 기본 식별자는 main이며, 예시 스니펫은 다음과 같습니다:

main: # 'main' is the GitLab 'provider ID' of this LDAP server
  label: 'LDAP'
  host: 'ldap.example.com'
  # ...
  group_base: 'cn=my_group,ou=groups,dc=example,dc=com'
  admin_group: 'my_admin_group'

LDAP 쿼리#

다음은 Rails 콘솔을 사용하여 LDAP에서 검색을 수행할 수 있게 해줍니다. 수행하려는 작업에 따라 사용자그룹을 직접 쿼리하거나, ldapsearch를 사용하는 것이 더 적합할 수도 있습니다.

adapter = Gitlab::Auth::Ldap::Adapter.new('ldapmain')
options = {
    # :base is required
    # use .base or .group_base
    base: adapter.config.group_base,

    # :filter is optional
    # 'cn' looks for all "cn"s under :base
    # '*' is the search string - here, it's a wildcard
    filter: Net::LDAP::Filter.eq('cn', '*'),

    # :attributes is optional
    # the attributes we want to get returned
    attributes: %w(dn cn memberuid member submember uniquemember memberof)
}
adapter.ldap_search(options)

필터에서 OID를 사용할 때는 Net::LDAP::Filter.eqNet::LDAP::Filter.construct로 교체하세요:

adapter = Gitlab::Auth::Ldap::Adapter.new('ldapmain')
options = {
    # :base is required
    # use .base or .group_base
    base: adapter.config.base,

    # :filter is optional
    # This filter includes OID 1.2.840.113556.1.4.1941
    # It will search for all direct and nested members of the group gitlab_grp in the LDAP directory
    filter: Net::LDAP::Filter.construct("(memberOf:1.2.840.113556.1.4.1941:=CN=gitlab_grp,DC=example,DC=com)"),

    # :attributes is optional
    # the attributes we want to get returned
    attributes: %w(dn cn memberuid member submember uniquemember memberof)
}
adapter.ldap_search(options)

실행 방법의 예시는 Adapter 모듈 검토를 참조하세요.

사용자 로그인#

사용자를 찾을 수 없음#

LDAP에 연결할 수 있음을 확인했지만 GitLab이 출력에 LDAP 사용자를 표시하지 않는 경우, 다음 중 하나가 해당될 가능성이 높습니다:

  • bind_dn 사용자에게 사용자 트리를 탐색할 충분한 권한이 없습니다.

  • 사용자가 설정된 base 아래에 속하지 않습니다.

  • 설정된 user_filter가 사용자에 대한 접근을 차단하고 있습니다.

이 경우, /etc/gitlab/gitlab.rb의 기존 LDAP 설정을 사용하여 ldapsearch로 이전 내용 중 어느 것이 사실인지 확인할 수 있습니다.

사용자가 로그인할 수 없음#

사용자는 여러 가지 이유로 로그인에 어려움을 겪을 수 있습니다. 시작하기 위해 스스로에게 다음과 같은 질문을 해보세요:

  • 사용자가 LDAP에서 설정된 base 아래에 속하나요? 사용자는 이 base 아래에 속해야 로그인할 수 있습니다.

  • 사용자가 설정된 user_filter를 통과하나요? 설정되지 않은 경우 이 질문은 무시할 수 있습니다. 설정된 경우, 사용자는 로그인이 허용되려면 이 필터도 통과해야 합니다.

user_filter 디버깅에 대한 문서를 참조하세요.

이전 질문이 모두 괜찮은 경우, 다음으로 살펴볼 곳은 문제를 재현하는 동안 로그 자체입니다.

  • 사용자에게 로그인을 요청하고 실패하도록 두세요.

  • 로그인에 관한 오류나 기타 메시지를 출력에서 확인하세요. 이 페이지의 다른 오류 메시지 중 하나가 표시될 수 있으며, 해당 섹션에서 문제를 해결하는 데 도움이 됩니다.

로그에서 문제의 근본 원인을 찾을 수 없는 경우, Rails 콘솔을 사용하여 이 사용자를 쿼리하여 GitLab이 LDAP 서버에서 이 사용자를 읽을 수 있는지 확인하세요.

추가 조사를 위해 사용자 동기화 디버깅도 도움이 될 수 있습니다.

사용자에게 "잘못된 로그인 또는 비밀번호" 오류가 표시됨#

히스토리

사용자에게 이 오류가 표시되는 경우, Standard 로그인 양식 대신 LDAP 로그인 양식을 사용하여 로그인을 시도하기 때문일 수 있습니다.

해결하려면, 사용자에게 LDAP 로그인 양식에 LDAP 사용자 이름과 비밀번호를 입력하도록 요청하세요.

로그인 시 잘못된 자격 증명#

사용된 로그인 자격 증명이 LDAP에서 정확하다면, 해당 사용자에 대해 다음이 사실인지 확인하세요:

  • 바인딩에 사용하는 사용자가 사용자의 트리를 읽고 탐색하기에 충분한 권한이 있는지 확인하세요.

  • user_filter가 그렇지 않으면 유효한 사용자를 차단하지 않는지 확인하세요.

  • LDAP 확인 명령을 실행하여 LDAP 설정이 올바른지, GitLab에서 사용자를 볼 수 있는지 확인하세요.

LDAP 계정에 대한 접근이 거부됨#

버그Auditor 수준 접근을 가진 사용자에게 영향을 줄 수 있습니다. Premium/Ultimate에서 다운그레이드할 때, 로그인을 시도하는 Auditor 사용자는 다음 메시지를 볼 수 있습니다: Access denied for your LDAP account.

해결 방법은 영향을 받은 사용자의 접근 수준을 변경하는 것입니다.

사전 요구 사항:

  • 관리자 접근 권한.

  • 오른쪽 상단 모서리에서 Admin을 선택하세요.

  • 왼쪽 사이드바에서 Overview > Users를 선택하세요.

  • 영향을 받은 사용자의 이름을 선택하세요.

  • 오른쪽 상단 모서리에서 Edit를 선택하세요.

  • 사용자의 접근 수준을 Regular에서 Administrator로 변경하세요(또는 그 반대로).

  • 페이지 하단에서 Save changes를 선택하세요.

  • 오른쪽 상단 모서리에서 다시 Edit를 선택하세요.

  • 사용자의 원래 접근 수준(Regular 또는 Administrator)을 복원하고 다시 Save changes를 선택하세요.

이제 사용자가 로그인할 수 있어야 합니다.

이메일이 이미 사용 중#

사용자가 올바른 LDAP 자격 증명으로 로그인을 시도하지만 접근이 거부되며, production.log에 다음과 같은 오류가 표시됩니다:

(LDAP) Error saving user  (email@example.com): ["Email has already been taken"]

이 오류는 LDAP의 이메일 주소 email@example.com을 참조합니다. GitLab에서 이메일 주소는 고유해야 하며, LDAP은 사용자의 기본 이메일(수많은 보조 이메일 중 하나가 아닌)에 연결됩니다. 다른 사용자(또는 동일한 사용자)가 보조 이메일로 email@example.com을 설정했기 때문에 이 오류가 발생합니다.

Rails 콘솔을 사용하여 이 충돌하는 이메일 주소의 출처를 확인할 수 있습니다. 콘솔에서 다음을 실행하세요:

# This searches for an email among the primary AND secondary emails
user = User.find_by_any_email('email@example.com')
user.username

이렇게 하면 어느 사용자가 이 이메일 주소를 가지고 있는지 알 수 있습니다. 여기에서 두 가지 단계 중 하나를 취해야 합니다:

  • LDAP으로 로그인할 때 이 사용자를 위한 새 GitLab 사용자/사용자 이름을 생성하려면, 충돌을 제거하기 위해 보조 이메일을 제거하세요.

  • 이 사용자가 LDAP과 함께 사용할 기존 GitLab 사용자/사용자 이름을 사용하려면, 이 이메일을 보조 이메일에서 제거하고 기본 이메일로 설정하여 GitLab이 이 프로필을 LDAP 신원과 연결하도록 하세요.

사용자는 프로필에서 이러한 단계 중 하나를 수행하거나 관리자가 수행할 수 있습니다.

프로젝트 제한 오류#

다음 오류는 제한 또는 제약이 활성화되어 있지만 관련 데이터 필드에 데이터가 없음을 나타냅니다:

  • Projects limit can't be blank.

  • Projects limit is not a number.

이를 해결하려면:

  • 오른쪽 상단 모서리에서 Admin을 선택하세요.

  • 왼쪽 사이드바에서 Settings > General을 선택하세요.

  • 다음 항목 모두를 확장하세요:

Account and limit.

  • New user account restrictions.

  • 예를 들어 Default projects limit 또는 Allowed domains for new user accounts 필드를 확인하고 관련 값이 설정되어 있는지 확인하세요.

LDAP 사용자 필터 디버깅#

ldapsearch를 사용하면 설정된 사용자 필터를 테스트하여 예상하는 사용자가 반환되는지 확인할 수 있습니다.

ldapsearch -H ldaps://$host:$port -D "$bind_dn" -y bind_dn_password.txt  -b "$base" "$user_filter" sAMAccountName
  • $로 시작하는 변수는 설정 파일의 LDAP 섹션에 있는 변수를 참조합니다.

  • 일반 인증 방법을 사용하는 경우 ldaps://ldap://로 교체하세요. 포트 389는 기본 ldap:// 포트이며, 636은 기본 ldaps:// 포트입니다.

  • bind_dn 사용자의 비밀번호가 bind_dn_password.txt에 있다고 가정합니다.

모든 사용자 동기화#

수동 사용자 동기화의 출력은 GitLab이 LDAP에 대해 사용자를 동기화하려고 할 때 어떤 일이 발생하는지 보여줄 수 있습니다. Rails 콘솔에 접속한 다음 실행하세요:

Rails.logger.level = Logger::DEBUG

LdapSyncWorker.new.perform

다음으로, 출력을 읽는 방법을 알아보세요.

사용자 동기화 후 콘솔 출력 예시#

수동 사용자 동기화의 출력은 매우 상세하며, 단일 사용자의 성공적인 동기화는 다음과 같을 수 있습니다:

Syncing user John, email@example.com
  Identity Load (0.9ms)  SELECT  "identities".* FROM "identities" WHERE "identities"."user_id" = 20 AND (provider LIKE 'ldap%') LIMIT 1
Instantiating Gitlab::Auth::Ldap::Person with LDIF:
dn: cn=John Smith,ou=people,dc=example,dc=com
cn: John Smith
mail: email@example.com
memberof: cn=admin_staff,ou=people,dc=example,dc=com
uid: John

  UserSyncedAttributesMetadata Load (0.9ms)  SELECT  "user_synced_attributes_metadata".* FROM "user_synced_attributes_metadata" WHERE "user_synced_attributes_metadata"."user_id" = 20 LIMIT 1
   (0.3ms)  BEGIN
  Namespace Load (1.0ms)  SELECT  "namespaces".* FROM "namespaces" WHERE "namespaces"."owner_id" = 20 AND "namespaces"."type" IS NULL LIMIT 1
  Route Load (0.8ms)  SELECT  "routes".* FROM "routes" WHERE "routes"."source_id" = 27 AND "routes"."source_type" = 'Namespace' LIMIT 1
  Ci::Runner Load (1.1ms)  SELECT "ci_runners".* FROM "ci_runners" INNER JOIN "ci_runner_namespaces" ON "ci_runners"."id" = "ci_runner_namespaces"."runner_id" WHERE "ci_runner_namespaces"."namespace_id" = 27
   (0.7ms)  COMMIT
   (0.4ms)  BEGIN
  Route Load (0.8ms)  SELECT "routes".* FROM "routes" WHERE (LOWER("routes"."path") = LOWER('John'))
  Namespace Load (1.0ms)  SELECT  "namespaces".* FROM "namespaces" WHERE "namespaces"."id" = 27 LIMIT 1
  Route Exists (0.9ms)  SELECT  1 AS one FROM "routes" WHERE LOWER("routes"."path") = LOWER('John') AND "routes"."id" != 50 LIMIT 1
  User Update (1.1ms)  UPDATE "users" SET "updated_at" = '2019-10-17 14:40:59.751685', "last_credential_check_at" = '2019-10-17 14:40:59.738714' WHERE "users"."id" = 20

여기에는 많은 내용이 있으므로, 디버깅 시 도움이 될 수 있는 내용을 살펴보겠습니다.

먼저, GitLab은 이전에 LDAP으로 로그인한 모든 사용자를 찾아 이들을 순회합니다. 각 사용자의 동기화는 현재 GitLab에 존재하는 사용자의 사용자 이름과 이메일이 포함된 다음 줄로 시작합니다:

Syncing user John, email@example.com

특정 사용자의 GitLab 이메일이 출력에 없는 경우, 해당 사용자는 아직 LDAP으로 로그인하지 않은 것입니다.

다음으로, GitLab은 이 사용자와 설정된 LDAP 공급자 사이의 기존 연결을 위해 identities 테이블을 검색합니다:

  Identity Load (0.9ms)  SELECT  "identities".* FROM "identities" WHERE "identities"."user_id" = 20 AND (provider LIKE 'ldap%') LIMIT 1

신원 객체에는 GitLab이 LDAP에서 사용자를 검색하는 데 사용하는 DN이 있습니다. DN이 없으면 대신 이메일을 사용합니다. 이 사용자가 LDAP에서 발견되었음을 알 수 있습니다:

Instantiating Gitlab::Auth::Ldap::Person with LDIF:
dn: cn=John Smith,ou=people,dc=example,dc=com
cn: John Smith
mail: email@example.com
memberof: cn=admin_staff,ou=people,dc=example,dc=com
uid: John

DN 또는 이메일로 사용자가 LDAP에서 발견되지 않으면, 다음 메시지가 대신 표시될 수 있습니다:

LDAP search error: No Such Object

이 경우 사용자가 차단됩니다:

  User Update (0.4ms)  UPDATE "users" SET "state" = $1, "updated_at" = $2 WHERE "users"."id" = $3  [["state", "ldap_blocked"], ["updated_at", "2019-10-18 15:46:22.902177"], ["id", 20]]

LDAP에서 사용자가 발견된 후, 나머지 출력은 변경 사항이 있으면 GitLab 데이터베이스를 업데이트합니다.

LDAP에서 사용자 쿼리#

이를 통해 GitLab이 LDAP에 연결하여 특정 사용자를 읽을 수 있는지 테스트합니다. GitLab UI에서 자동으로 실패하는 것처럼 보이는 LDAP 연결 및/또는 쿼리 오류를 노출할 수 있습니다.

Rails.logger.level = Logger::DEBUG

adapter = Gitlab::Auth::Ldap::Adapter.new('ldapmain') # If `main` is the LDAP provider
Gitlab::Auth::Ldap::Person.find_by_uid('<uid>', adapter)

머지 리퀘스트 승인 규칙#

LDAP 연결 문제가 발생하면, 동기화 작업 중에 사용자가 머지 리퀘스트 승인 규칙에서 제거될 수 있습니다. 이로 인해 승인 규칙이 비워지고 유효하지 않은 것으로 표시될 수 있습니다.

LDAP 연결이 끊어질 때 승인 규칙 실패#

LDAP 서버가 일시적으로 사용 불가능하거나 바인드 계정이 실패하는 경우:

  • LDAP 기반 승인 규칙에 설정된 사용자가 다음 동기화 주기 중에 제거될 수 있습니다.

  • 남은 사용자가 없는 승인 규칙은 유효하지 않은 것으로 표시됩니다.

  • 표준 승인 규칙은 Auto approved로 표시되며 더 이상 머지를 차단하지 않습니다.

  • 머지 리퀘스트 승인 정책 규칙은 Action required로 표시되며 계속 머지를 차단합니다.

표준 승인 규칙이 자동으로 우회되는 것을 방지하려면:

  • LDAP 서버가 고가용성과 안정적인 연결성을 갖추도록 하세요.

  • LDAP 동기화 작업의 실패를 모니터링하세요.

  • 중요한 보안 요구 사항에는 표준 승인 규칙 대신 머지 리퀘스트 승인 정책을 사용하세요. 승인 정책은 더 강력한 적용을 제공하며 자동으로 실패하지 않습니다.

승인 규칙 동작에 대한 자세한 내용은 유효하지 않은 규칙을 참조하세요.

LDAP 문제로 인해 사용자가 승인 규칙에서 제거되면 LDAP 연결이 복원되어도 자동으로 다시 추가되지 않습니다. 승인 규칙을 수동으로 복원하거나 백업에서 복구해야 할 수 있습니다.

그룹 멤버십#

멤버십이 부여되지 않음#

때로는 특정 사용자가 LDAP 그룹 동기화를 통해 GitLab 그룹에 추가되어야 한다고 생각하지만, 어떤 이유로 그렇게 되지 않을 수 있습니다. 상황을 디버깅하기 위해 여러 가지를 확인할 수 있습니다.

  • LDAP 설정에 group_base가 지정되어 있는지 확인하세요. 이 설정은 그룹 동기화가 제대로 작동하기 위해 필요합니다.

  • 올바른 LDAP 그룹 링크가 GitLab 그룹에 추가되어 있는지 확인하세요.

  • 사용자에게 LDAP 신원이 있는지 확인하세요:

관리자 사용자로 GitLab에 로그인하세요.

  • 오른쪽 상단 모서리에서 Admin을 선택하세요.

  • 왼쪽 사이드바에서 Overview > Users를 선택하세요.

  • 사용자를 검색하세요.

  • 사용자의 이름을 선택하여 열어보세요. Edit는 선택하지 마세요.

  • Identities 탭을 선택하세요. Identifier로 LDAP DN이 있는 LDAP 신원이 있어야 합니다. 없다면, 이 사용자는 아직 LDAP으로 로그인하지 않았으므로 먼저 로그인해야 합니다.

  • 그룹이 동기화되도록 한 시간 또는 설정된 간격을 기다렸습니다. 프로세스를 빠르게 진행하려면, GitLab 그룹 Manage > Members로 이동하여 Sync now(한 그룹 동기화)를 누르거나 그룹 동기화 Rake 태스크를 실행(모든 그룹 동기화)하세요.

모든 확인이 양호한 경우, Rails 콘솔에서 좀 더 고급 디버깅을 진행하세요.

  • Rails 콘솔에 접속하세요.

  • 테스트할 GitLab 그룹을 선택하세요. 이 그룹에는 이미 LDAP 그룹 링크가 설정되어 있어야 합니다.

  • 디버그 로깅을 활성화하고, 선택된 GitLab 그룹을 찾아 LDAP와 동기화하세요.

  • 동기화 출력을 살펴보세요. 출력을 읽는 방법은 예시 로그 출력을 참조하세요.

  • 사용자가 추가되지 않는 이유를 여전히 알 수 없는 경우, LDAP 그룹을 직접 쿼리하여 어떤 멤버가 나열되어 있는지 확인하세요.

  • 쿼리된 그룹의 목록 중 하나에 사용자의 DN 또는 UID가 있나요? 여기의 DN 또는 UID 중 하나는 앞서 확인한 LDAP 신원의 'Identifier'와 일치해야 합니다. 일치하지 않으면 사용자가 LDAP 그룹에 없는 것으로 보입니다.

LDAP 동기화가 활성화된 경우 서비스 계정 사용자를 그룹에 추가할 수 없음#

그룹에 LDAP 동기화가 활성화된 경우, "invite" 대화 상자를 사용하여 새 그룹 멤버를 초대할 수 없습니다.

GitLab 16.8 이상에서 이 문제를 해결하려면, 그룹 멤버 API 엔드포인트를 사용하여 서비스 계정을 그룹에 초대하거나 제거할 수 있습니다.

관리자 권한이 부여되지 않음#

LDAP 그룹에 관리자 권한을 할당했지만 설정된 사용자에게 올바른 관리자 권한이 부여되지 않는 경우, 다음 조건이 사실인지 확인하세요:

  • group_base가 설정되어 있는지 확인하세요.

  • gitlab.rb의 설정된 admin_group이 DN이나 배열이 아닌 CN인지 확인하세요.

  • 이 CN이 설정된 group_base의 범위 내에 있는지 확인하세요.

  • admin_group의 멤버가 이미 LDAP 자격 증명으로 GitLab에 로그인했는지 확인하세요. GitLab은 LDAP에 이미 연결된 계정을 가진 사용자에게만 관리자 접근을 부여합니다.

이전 조건이 모두 사실이고 사용자가 여전히 접근 권한을 얻지 못하는 경우, Rails 콘솔에서 수동 그룹 동기화를 실행하고 출력을 살펴보아 GitLab이 admin_group을 동기화할 때 어떤 일이 발생하는지 확인하세요.

UI에서 Sync now 버튼이 멈춤#

그룹의 Group > Members 페이지에 있는 Sync now 버튼이 멈출 수 있습니다. 버튼이 눌리고 페이지가 새로 고쳐진 후 멈추게 됩니다. 그러면 버튼을 다시 선택할 수 없습니다.

Sync now 버튼은 여러 가지 이유로 멈출 수 있으며 특정 케이스에 대한 디버깅이 필요합니다. 다음은 두 가지 가능한 원인과 문제에 대한 가능한 해결책입니다.

유효하지 않은 멤버십#

Sync now 버튼은 그룹의 멤버 또는 요청 멤버 중 일부가 유효하지 않은 경우 멈춥니다. 이 문제의 가시성을 개선하는 진행 상황은 관련 이슈에서 확인할 수 있습니다. Rails 콘솔을 사용하여 이 문제가 Sync now 버튼이 멈추는 원인인지 확인할 수 있습니다:

# Find the group in question
group = Group.find_by(name: 'my_gitlab_group')

# Look for errors on the Group itself
group.valid?
group.errors.map(&:full_messages)

# Look for errors among the group's members and requesters
group.requesters.map(&:valid?)
group.requesters.map(&:errors).map(&:full_messages)
group.members.map(&:valid?)
group.members.map(&:errors).map(&:full_messages)

표시된 오류는 문제를 식별하고 해결책을 제시할 수 있습니다. 예를 들어, 지원 팀에서는 다음 오류를 확인했습니다:

irb(main):018:0> group.members.map(&:errors).map(&:full_messages)
=> [["The member's email address is not allowed for this group. Go to the group's 'Settings > General' page, and check 'Restrict membership by email domain'."]]

이 오류는 관리자가 이메일 도메인으로 그룹 멤버십을 제한하도록 선택했지만, 도메인에 오타가 있음을 보여주었습니다. 도메인 설정이 수정된 후, Sync now 버튼이 다시 정상적으로 작동했습니다.

Sidekiq 노드에 LDAP 설정이 없음#

GitLab이 여러 노드로 확장되어 있고 Sidekiq를 실행하는 노드의 /etc/gitlab/gitlab.rb에 LDAP 설정이 없는 경우, Sync now 버튼이 멈춥니다. 이 경우, Sidekiq 작업이 사라지는 것처럼 보입니다.

Sidekiq 노드에 LDAP가 필요한 이유는 LDAP에 로컬 LDAP 설정이 필요한 비동기적으로 실행되는 여러 작업이 있기 때문입니다:

Sidekiq를 실행하는 각 노드에서 LDAP를 확인하는 Rake 태스크를 실행하여 LDAP 설정 누락이 문제인지 테스트할 수 있습니다. LDAP가 이 노드에 올바르게 설정되어 있으면 LDAP 서버에 연결하고 사용자를 반환합니다.

이 문제를 해결하려면, Sidekiq 노드에 LDAP를 설정하세요. 설정 후, LDAP를 확인하는 Rake 태스크를 실행하여 GitLab 노드가 LDAP에 연결할 수 있는지 확인하세요.

모든 그룹 동기화#

디버깅이 필요하지 않을 때 모든 그룹을 수동으로 동기화하려면, Rake 태스크를 사용하세요.

수동 그룹 동기화의 출력은 GitLab이 LDAP 그룹 멤버십을 LDAP에 대해 동기화할 때 어떤 일이 발생하는지 보여줄 수 있습니다. Rails 콘솔에 접속한 다음 실행하세요:

Rails.logger.level = Logger::DEBUG

LdapAllGroupsSyncWorker.new.perform

다음으로, 출력을 읽는 방법을 알아보세요.

그룹 동기화 후 콘솔 출력 예시#

사용자 동기화 출력과 마찬가지로, 수동 그룹 동기화의 출력도 매우 상세합니다. 그러나 많은 유용한 정보가 포함되어 있습니다.

동기화가 실제로 시작되는 지점을 나타냅니다:

Started syncing 'ldapmain' provider for 'my_group' group

다음 항목은 GitLab이 LDAP 서버에서 볼 수 있는 모든 사용자 DN의 배열을 보여줍니다. 이 DN들은 GitLab 그룹이 아닌 단일 LDAP 그룹의 사용자입니다. 이 GitLab 그룹에 여러 LDAP 그룹이 연결되어 있는 경우, 이와 같은 여러 로그 항목(각 LDAP 그룹당 하나)이 표시됩니다. 이 로그 항목에서 LDAP 사용자 DN이 보이지 않으면, 조회를 할 때 LDAP에서 해당 사용자를 반환하지 않는 것입니다. 사용자가 실제로 LDAP 그룹에 있는지 확인하세요.

Members in 'ldap_group_1' LDAP group: ["uid=john0,ou=people,dc=example,dc=com",
"uid=mary0,ou=people,dc=example,dc=com", "uid=john1,ou=people,dc=example,dc=com",
"uid=mary1,ou=people,dc=example,dc=com", "uid=john2,ou=people,dc=example,dc=com",
"uid=mary2,ou=people,dc=example,dc=com", "uid=john3,ou=people,dc=example,dc=com",
"uid=mary3,ou=people,dc=example,dc=com", "uid=john4,ou=people,dc=example,dc=com",
"uid=mary4,ou=people,dc=example,dc=com"]

각 항목 직후에 해결된 멤버 접근 수준의 해시가 표시됩니다. 이 해시는 GitLab이 이 그룹에 접근 권한이 있어야 한다고 생각하는 모든 사용자 DN과 접근 수준(권한)을 나타냅니다. 이 해시는 누적되며, 추가 LDAP 그룹 조회를 기반으로 더 많은 DN이 추가되거나 기존 항목이 수정될 수 있습니다. 이 항목의 마지막 발생은 GitLab이 그룹에 추가해야 한다고 생각하는 사용자를 정확히 나타냅니다.

10은 Guest, 20은 Reporter, 25는 Security Manager, 30은 Developer, 40은 Maintainer, 50은 Owner입니다.

Resolved 'my_group' group member access: {"uid=john0,ou=people,dc=example,dc=com"=>30,
"uid=mary0,ou=people,dc=example,dc=com"=>30, "uid=john1,ou=people,dc=example,dc=com"=>30,
"uid=mary1,ou=people,dc=example,dc=com"=>30, "uid=john2,ou=people,dc=example,dc=com"=>30,
"uid=mary2,ou=people,dc=example,dc=com"=>30, "uid=john3,ou=people,dc=example,dc=com"=>30,
"uid=mary3,ou=people,dc=example,dc=com"=>30, "uid=john4,ou=people,dc=example,dc=com"=>30,
"uid=mary4,ou=people,dc=example,dc=com"=>30}

다음과 같은 경고가 표시되는 것은 드문 일이 아닙니다. 이는 GitLab이 사용자를 그룹에 추가했을 것이지만 사용자가 GitLab에서 찾을 수 없음을 나타냅니다. 일반적으로 이것은 걱정할 필요가 없습니다.

특정 사용자가 이미 GitLab에 존재해야 한다고 생각하지만 이 항목이 표시되는 경우, GitLab에 저장된 DN이 일치하지 않기 때문일 수 있습니다. 사용자의 LDAP 신원을 업데이트하려면 사용자 DN 및 이메일이 변경됨을 참조하세요.

User with DN `uid=john0,ou=people,dc=example,dc=com` should have access
to 'my_group' group but there is no user in GitLab with that
identity. Membership will be updated when the user signs in for
the first time.

마지막으로, 다음 항목은 이 그룹의 동기화가 완료되었음을 나타냅니다:

Finished syncing all providers for 'my_group' group

설정된 모든 그룹 링크가 동기화된 후, GitLab은 동기화할 관리자 또는 외부 사용자를 찾습니다:

Syncing admin users for 'ldapmain' provider

출력은 단일 그룹과 유사하게 보이며, 이 줄은 동기화가 완료되었음을 나타냅니다:

Finished syncing admin users for 'ldapmain' provider

관리자 권한을 할당하지 않은 경우, 이 메시지가 표시됩니다:

No `admin_group` configured for 'ldapmain' provider. Skipping

하나의 그룹 동기화#

모든 그룹 동기화는 단일 GitLab 그룹의 멤버십만 문제 해결하려는 경우 산만할 수 있는 많은 출력을 생성할 수 있습니다. 이 경우, 이 그룹만 동기화하고 디버그 출력을 보는 방법은 다음과 같습니다:

Rails.logger.level = Logger::DEBUG

# Find the GitLab group.
# If the output is `nil`, the group could not be found.
# If a bunch of group attributes are in the output, your group was found successfully.
group = Group.find_by(name: 'my_gitlab_group')

# Sync this group against LDAP
EE::Gitlab::Auth::Ldap::Sync::Group.execute_all_providers(group)

출력은 모든 그룹 동기화에서 얻는 출력과 유사합니다.

LDAP에서 그룹 쿼리#

GitLab이 LDAP 그룹을 읽고 모든 멤버를 볼 수 있는지 확인하려면, 다음을 실행할 수 있습니다:

# Find the adapter and the group itself
adapter = Gitlab::Auth::Ldap::Adapter.new('ldapmain') # If `main` is the LDAP provider
ldap_group = EE::Gitlab::Auth::Ldap::Group.find_by_cn('group_cn_here', adapter)

# Find the members of the LDAP group
ldap_group.member_dns
ldap_group.member_uids

LDAP 동기화가 그룹에서 그룹 생성자를 제거하지 않음#

LDAP 동기화는 LDAP 그룹에 해당 사용자가 존재하지 않는 경우, LDAP 그룹의 생성자를 그룹에서 제거해야 합니다. LDAP 동기화를 실행해도 이 작업이 수행되지 않는 경우:

  • LDAP 그룹에 사용자를 추가하세요.

  • LDAP 그룹 동기화가 실행이 완료될 때까지 기다리세요.

  • LDAP 그룹에서 사용자를 제거하세요.

사용자 DN 및 이메일이 변경됨#

LDAP에서 기본 이메일과 DN이 모두 변경된 경우, GitLab은 사용자의 올바른 LDAP 레코드를 식별할 수 없습니다. 결과적으로 GitLab은 해당 사용자를 차단합니다. GitLab이 LDAP 레코드를 찾을 수 있도록, 사용자의 기존 GitLab 프로필을 다음 중 최소 하나 이상으로 업데이트하세요:

  • 새 기본 이메일.

  • DN 값.

다음 스크립트는 제공된 모든 사용자의 이메일을 업데이트하여 차단되거나 계정에 접근할 수 없게 되는 일이 없도록 합니다.

다음 스크립트를 사용하기 전에 새 이메일 주소를 가진 새 계정이 먼저 제거되어야 합니다. GitLab에서 이메일 주소는 고유해야 합니다.

Rails 콘솔로 이동한 다음 실행하세요:

# Each entry must include the old username and the new email
emails = {
  'ORIGINAL_USERNAME' => 'NEW_EMAIL_ADDRESS',
  ...
}

emails.each do |username, email|
  user = User.find_by_username(username)
  user.email = email
  user.skip_reconfirmation!
  user.save!
end

그런 다음 UserSync를 실행하여 이 사용자들 각각에 대한 최신 DN을 동기화할 수 있습니다.

AzureActivedirectoryV2에서 Invalid grant로 인해 인증할 수 없음#

LDAP에서 SAML로 변환할 때 Azure에서 다음과 같은 오류가 발생할 수 있습니다:

Authentication failure! invalid_credentials: OAuth2::Error, invalid_grant.

이 문제는 다음 조건이 모두 해당할 때 발생합니다:

  • SAML이 해당 사용자에게 설정된 후에도 LDAP 신원이 여전히 존재합니다.

  • 해당 사용자에 대해 LDAP를 비활성화했습니다.

로그에 LDAP와 Azure 메타데이터가 모두 포함되어 Azure에서 오류가 생성됩니다.

단일 사용자에 대한 해결 방법은 Admin > Identities에서 사용자의 LDAP 신원을 제거하는 것입니다.

여러 LDAP 신원을 제거하려면, 아래 Could not authenticate you from Ldapmain because "Unknown provider" 오류에 대한 해결 방법 중 하나를 사용하세요.

오류: Ldapmain에서 "Unknown provider"로 인해 인증할 수 없음#

LDAP 서버로 인증할 때 다음 오류가 발생할 수 있습니다:

Could not authenticate you from Ldapmain because "Unknown provider (ldapsecondary). available providers: ["ldapmain"]".

이 오류는 이름이 변경되거나 GitLab 설정에서 제거된 LDAP 서버로 이전에 인증한 계정을 사용할 때 발생합니다. 예를 들어:

  • 처음에는 GitLab 설정의 ldap_serversmainsecondary가 설정되어 있습니다.

  • secondary 설정이 제거되거나 main으로 이름이 변경됩니다.

  • 로그인을 시도하는 사용자가 secondary에 대한 identify 레코드를 가지고 있지만, 더 이상 설정되어 있지 않습니다.

Rails 콘솔을 사용하여 영향을 받은 사용자를 나열하고 어떤 LDAP 서버에 대한 신원이 있는지 확인하세요:

ldap_identities = Identity.where(provider: "ldapsecondary")
ldap_identities.each do |identity|
  u=User.find_by_id(identity.user_id)
  ui=Identity.where(user_id: identity.user_id)
  puts "user: #{u.username}\n   #{u.email}\n   last activity: #{u.last_activity_on}\n   #{identity.provider} ID: #{identity.id} external: #{identity.extern_uid}"
  puts "   all identities:"
  ui.each do |alli|
    puts "    - #{alli.provider} ID: #{alli.id} external: #{alli.extern_uid}"
  end
end;nil

이 오류는 두 가지 방법으로 해결할 수 있습니다.

LDAP 서버에 대한 참조 이름 변경#

이 해결 방법은 LDAP 서버가 서로의 복제본이고, 영향을 받은 사용자가 설정된 LDAP 서버를 사용하여 로그인할 수 있어야 하는 경우에 적합합니다. 예를 들어, 이제 로드 밸런서를 사용하여 LDAP 고가용성을 관리하고 별도의 보조 로그인 옵션이 더 이상 필요하지 않은 경우입니다.

LDAP 서버가 서로의 복제본이 아닌 경우, 이 해결 방법은 영향을 받은 사용자가 로그인할 수 없게 합니다.

더 이상 설정되지 않은 LDAP 서버에 대한 참조 이름을 변경하려면 실행하세요:

sudo gitlab-rake gitlab:ldap:rename_provider[ldapsecondary,ldapmain]

제거된 LDAP 서버와 관련된 신원 레코드 제거#

사전 요구 사항:

  • auto_link_ldap_user가 활성화되어 있는지 확인하세요.

이 해결 방법을 사용하면, 신원이 삭제된 후 영향을 받은 사용자가 설정된 LDAP 서버로 로그인할 수 있으며 GitLab에서 새로운 identity 레코드가 생성됩니다.

제거된 LDAP 서버가 ldapsecondary이므로, Rails 콘솔에서 모든 ldapsecondary 신원을 삭제하세요:

ldap_identities = Identity.where(provider: "ldapsecondary")
ldap_identities.each do |identity|
  puts "Destroying identity: #{identity.id} #{identity.provider}: #{identity.extern_uid}"
  identity.destroy!
rescue => e
  puts 'Error generated when destroying identity:\n ' + e.to_s
end; nil

만료된 라이선스로 인해 여러 LDAP 서버에서 오류 발생#

여러 LDAP 서버를 사용하려면 유효한 라이선스가 필요합니다. 만료된 라이선스는 다음을 유발할 수 있습니다:

  • 웹 인터페이스에서 502 오류.

  • 로그의 다음 오류(실제 전략 이름은 /etc/gitlab/gitlab.rb에 설정된 이름에 따라 다름):

Could not find a strategy with name `Ldapsecondary'. Please ensure it is required or explicitly set it using the :strategy_class option. (Devise::OmniAuth::StrategyNotFound)

이 오류를 해결하려면, 웹 인터페이스 없이 GitLab 인스턴스에 새 라이선스를 적용해야 합니다:

사용자가 그룹에서 제거되고 다시 추가됨#

사용자가 그룹 동기화 중에 그룹에 추가되었다가 다음 동기화 시 제거되는 일이 반복된다면, 사용자에게 여러 개 또는 중복된 LDAP 신원이 없는지 확인하세요.

이러한 신원 중 하나가 더 이상 사용하지 않는 이전 LDAP 공급자에 대해 추가된 경우, 제거된 LDAP 서버와 관련된 identity 레코드를 제거하세요.

디버깅 도구#

LDAP 확인#

LDAP를 확인하는 Rake 태스크는 GitLab이 LDAP에 성공적으로 연결을 설정하고 사용자를 읽을 수 있는지 확인하는 데 도움이 되는 유용한 도구입니다.

연결을 설정할 수 없는 경우, 설정 문제나 방화벽이 연결을 차단하고 있기 때문일 가능성이 높습니다.

  • 방화벽이 연결을 차단하지 않는지, LDAP 서버가 GitLab 호스트에서 접근 가능한지 확인하세요.

  • Rake 확인 출력에서 오류 메시지를 찾아보세요. 이는 LDAP 설정(특히 host, port, bind_dn, password)이 올바른지 확인하는 데 도움이 됩니다.

  • 연결 실패를 더 디버깅하려면 로그에서 오류를 찾아보세요.

GitLab이 LDAP에 성공적으로 연결할 수 있지만 사용자를 반환하지 않으면, 사용자를 찾을 수 없을 때 해야 할 일을 참조하세요.

GitLab 로그#

LDAP 설정으로 인해 사용자 계정이 차단되거나 차단 해제되면, application_json.log에 메시지가 기록됩니다.

LDAP 조회 중에 예기치 않은 오류(설정 오류, 시간 초과)가 발생하면, 로그인이 거부되고 production.log에 메시지가 기록됩니다.

ldapsearch#

ldapsearch는 LDAP 서버를 쿼리할 수 있는 유틸리티입니다. LDAP 설정을 테스트하고 사용 중인 설정이 원하는 결과를 제공하는지 확인하는 데 사용할 수 있습니다.

ldapsearch를 사용할 때, gitlab.rb 설정에 이미 지정한 것과 동일한 설정을 사용하여 정확한 설정을 사용할 때 어떤 일이 발생하는지 확인하세요.

GitLab 호스트에서 이 명령을 실행하면 GitLab 호스트와 LDAP 사이에 장애물이 없는지도 확인하는 데 도움이 됩니다.

예를 들어, 다음 GitLab 설정을 고려하세요:

gitlab_rails['ldap_servers'] = YAML.load <<-'EOS' # remember to close this block with 'EOS' below
   main: # 'main' is the GitLab 'provider ID' of this LDAP server
     label: 'LDAP'
     host: '127.0.0.1'
     port: 389
     uid: 'uid'
     encryption: 'plain'
     bind_dn: 'cn=admin,dc=ldap-testing,dc=example,dc=com'
     password: 'Password1'
     active_directory: true
     allow_username_or_email_login: false
     block_auto_created_users: false
     base: 'dc=ldap-testing,dc=example,dc=com'
     user_filter: ''
     attributes:
       username: ['uid', 'userid', 'sAMAccountName']
       email:    ['mail', 'email', 'userPrincipalName']
       name:       'cn'
       first_name: 'givenName'
       last_name:  'sn'
     group_base: 'ou=groups,dc=ldap-testing,dc=example,dc=com'
     admin_group: 'gitlab_admin'
EOS

bind_dn 사용자를 찾기 위해 다음 ldapsearch를 실행하세요:

ldapsearch -D "cn=admin,dc=ldap-testing,dc=example,dc=com" \
  -w Password1 \
  -p 389 \
  -h 127.0.0.1 \
  -b "dc=ldap-testing,dc=example,dc=com"

bind_dn, password, port, host, base는 모두 gitlab.rb에 설정된 것과 동일합니다.

start_tls 암호화로 ldapsearch 사용#

이전 예시는 포트 389에 평문으로 LDAP 테스트를 수행합니다. start_tls 암호화를 사용하는 경우, ldapsearch 명령에 다음을 포함하세요:

  • -Z 플래그.

  • LDAP 서버의 FQDN.

TLS 협상 중에 LDAP 서버의 FQDN이 인증서와 대조되어 평가되기 때문에 이를 포함해야 합니다:

ldapsearch -D "cn=admin,dc=ldap-testing,dc=example,dc=com" \
  -w Password1 \
  -p 389 \
  -h "testing.ldap.com" \
  -b "dc=ldap-testing,dc=example,dc=com" -Z

simple_tls 암호화로 ldapsearch 사용#

simple_tls 암호화(일반적으로 포트 636)를 사용하는 경우, ldapsearch 명령에 다음을 포함하세요:

  • -H 플래그와 포트를 사용한 LDAP 서버 FQDN.

  • 완전히 구성된 URI.

ldapsearch -D "cn=admin,dc=ldap-testing,dc=example,dc=com" \
  -w Password1 \
  -H "ldaps://testing.ldap.com:636" \
  -b "dc=ldap-testing,dc=example,dc=com"

자세한 내용은 공식 ldapsearch 문서를 참조하세요.

AdFind 사용 (Windows)#

AdFind 유틸리티(Windows 기반 시스템에서)를 사용하여 LDAP 서버에 접근 가능하고 인증이 올바르게 작동하는지 테스트할 수 있습니다. AdFind은 Joe Richards가 만든 프리웨어 유틸리티입니다.

모든 객체 반환

objectclass=* 필터를 사용하여 모든 디렉터리 객체를 반환할 수 있습니다.

adfind -h ad.example.org:636 -ssl -u "CN=GitLabSRV,CN=Users,DC=GitLab,DC=org" -up Password1 -b "OU=GitLab INT,DC=GitLab,DC=org" -f (objectClass=*)

필터를 사용하여 단일 객체 반환

객체 이름이나 전체 DN지정하여 단일 객체를 검색할 수도 있습니다. 이 예시에서는 객체 이름 CN=Leroy Fox만 지정합니다.

adfind -h ad.example.org:636 -ssl -u "CN=GitLabSRV,CN=Users,DC=GitLab,DC=org" -up Password1 -b "OU=GitLab INT,DC=GitLab,DC=org" -f "(&(objectcategory=person)(CN=Leroy Fox))"

Rails 콘솔#

Rails 콘솔로 데이터를 생성, 읽기, 수정, 삭제하는 것은 매우 쉽습니다. 명령을 정확하게 나열된 대로 실행하세요.

Rails 콘솔은 LDAP 문제를 디버깅하는 데 도움이 되는 유용한 도구입니다. 명령을 실행하고 GitLab이 이에 어떻게 응답하는지 확인하여 애플리케이션과 직접 상호 작용할 수 있습니다.

Rails 콘솔 사용 방법에 대한 지침은 이 가이드를 참조하세요.

디버그 출력 활성화#

이것은 GitLab이 무엇을 하고 있으며 무엇으로 하고 있는지 보여주는 디버그 출력을 제공합니다. 이 값은 지속되지 않으며, Rails 콘솔의 이 세션에서만 활성화됩니다.

Rails 콘솔에서 디버그 출력을 활성화하려면, Rails 콘솔에 접속하고 실행하세요:

Rails.logger.level = Logger::DEBUG

그룹, 하위 그룹, 멤버 및 요청자와 관련된 모든 오류 메시지 가져오기#

그룹, 하위 그룹, 멤버 및 요청자와 관련된 오류 메시지를 수집하세요. 이는 웹 인터페이스에 표시되지 않을 수 있는 오류 메시지를 캡처합니다. LDAP 그룹 동기화 문제 해결과 그룹 및 하위 그룹의 사용자 및 멤버십과 관련된 예기치 않은 동작에 특히 도움이 될 수 있습니다.

# Find the group and subgroup
group = Group.find_by_full_path("parent_group")
subgroup = Group.find_by_full_path("parent_group/child_group")

# Group and subgroup errors
group.valid?
group.errors.map(&:full_messages)

subgroup.valid?
subgroup.errors.map(&:full_messages)

# Group and subgroup errors for the members AND requesters
group.requesters.map(&:valid?)
group.requesters.map(&:errors).map(&:full_messages)
group.members.map(&:valid?)
group.members.map(&:errors).map(&:full_messages)
group.members_and_requesters.map(&:errors).map(&:full_messages)

subgroup.requesters.map(&:valid?)
subgroup.requesters.map(&:errors).map(&:full_messages)
subgroup.members.map(&:valid?)
subgroup.members.map(&:errors).map(&:full_messages)
subgroup.members_and_requesters.map(&:errors).map(&:full_messages)