Jenkins 보안 문제 해결: 액세스 거부 및 권한 부여 오류
Jenkins에서 '액세스 거부' 또는 권한 부여 오류가 발생하시나요? 이 포괄적인 가이드는 일반적인 보안 문제를 진단하고 해결하는 방법을 안내합니다. 인증과 권한 부여의 차이점, 보안 영역 및 전략 구성 확인 방법, 시스템 로그 해석 방법, CSRF 보호 문제 해결 방법을 알아보세요. 실용적인 문제 해결 단계, 긴급 액세스 절차, Jenkins 인스턴스를 보호하고 승인된 액세스와 강력한 CI/CD 파이프라인을 보장하기 위한 필수 모범 사례를 발견하세요.
Jenkins 보안 문제 해결: 액세스 거부 및 권한 부여 오류
Jenkins 액세스 문제는 누군가 배포, 실패한 빌드 재실행, 또는 프로덕션 수정이 필요할 때 자주 발생하기 때문에 스트레스를 줍니다. 오류 메시지는 Access Denied, Missing permission, 403 No valid crumb, anonymous is missing Overall/Read 등으로 나타나거나 단순히 사용자를 로그인 페이지로 되돌려 보낼 수 있습니다. 이러한 메시지는 비슷해 보이지만 Jenkins 보안의 다른 부분을 가리킵니다.
Jenkins 보안 문제 해결을 위한 가장 빠른 방법은 세 가지 질문을 분리하는 것입니다: Jenkins가 사용자를 인식했는지, Jenkins가 올바른 권한을 부여했는지, 요청이 Jenkins의 요청 보호를 통과했는지입니다. 인증, 권한 부여, CSRF 보호는 별개의 계층입니다. 이를 하나의 모호한 "로그인 문제"로 취급하면 시간이 낭비됩니다.
Jenkins 보안 기본 사항 이해
문제 해결에 들어가기 전에 Jenkins 보안의 핵심 개념인 인증과 권한 부여를 이해하는 것이 중요합니다.
인증 vs 권한 부여
- 인증: 사용자의 신원을 확인하는 과정입니다. "당신은 누구인가요?"라는 질문에 답합니다. 사용자 이름과 비밀번호로 로그인하면 Jenkins는 보안 영역에 대해 사용자를 인증합니다.
- 권한 부여: 인증된 사용자가 무엇을 할 수 있는지 결정하는 과정입니다. "여기서 무엇을 할 수 있나요?"라는 질문에 답합니다. Jenkins가 사용자가 누구인지 알게 되면 권한 부여 전략에 따라 사용자의 권한을 확인하여 작업을 볼 수 있는지, 시스템을 구성할 수 있는지, 빌드를 시작할 수 있는지 결정합니다.
Jenkins 보안 영역 (인증)
보안 영역은 Jenkins가 사용자를 어떻게 인증하는지 정의합니다. 일반적인 옵션은 다음과 같습니다:
- Jenkins 자체 사용자 데이터베이스: 사용자가 Jenkins 내에서 직접 생성 및 관리됩니다.
- LDAP: 기존 LDAP 서버(예: Active Directory)와 통합하여 사용자를 인증합니다.
- Unix 사용자/그룹 데이터베이스: 기본 운영 체제의 사용자 계정에 대해 인증합니다.
- SAML / OAuth: Single Sign-On을 위해 ID 공급자와 통합합니다.
Jenkins 권한 부여 전략
권한 부여 전략은 인증된 사용자가 무엇을 할 수 있는지 정의합니다. 주요 전략은 다음과 같습니다:
- 로그인한 사용자는 모든 작업 가능: 간단하지만 일반적으로 프로덕션에는 너무 광범위합니다. 로그인할 수 있는 사람은 누구나 관리자 수준의 권한을 가집니다.
- 레거시 모드: 이전 설치와의 호환성을 위해 유지됩니다. 프로덕션 시스템에는 피하십시오.
- 매트릭스 기반 보안: 전역 및 프로젝트별 컨텍스트에서 개별 사용자/그룹에 대한 세분화된 권한 제어를 허용합니다.
- 프로젝트 기반 매트릭스 권한 부여 전략: 매트릭스 기반 보안의 확장으로, 프로젝트별 권한이 전역 설정을 재정의할 수 있도록 합니다.
- 역할 기반 전략 플러그인: 사용자를 역할에 할당하고 역할을 특정 권한(전역, 폴더 또는 프로젝트 수준)에 할당하여 권한 관리를 단순화하는 인기 있는 플러그인입니다.
'액세스 거부' 오류로 이어지는 일반적인 시나리오
'액세스 거부' 또는 유사한 권한 부여 오류는 일반적으로 다음 상황 중 하나에서 발생합니다:
- 잘못된 자격 증명: 간단히 잘못 입력한 사용자 이름 또는 비밀번호.
- 사용자를 찾을 수 없음: 로그인하려는 사용자가 구성된 보안 영역에 존재하지 않습니다.
- 권한 부족: 사용자는 인증되었지만 요청된 작업(예: 작업 보기, 시스템 설정 구성)을 수행하는 데 필요한 권한이 없습니다.
- 보안 영역 구성 문제: 외부 인증 소스(예: LDAP 서버 다운, 잘못된 바인드 DN)에 대한 연결 문제.
- CSRF 보호: Jenkins의 내장된 Cross-Site Request Forgery 보호가 합법적인 프로그래매틱 요청(예: 스크립트 또는 외부 도구에서)을 차단합니다.
- 플러그인 충돌 또는 잘못된 구성: 보안 관련 플러그인(예: 역할 기반 전략)이 잘못 구성되었거나 다른 플러그인과 충돌합니다.
- Jenkins 업그레이드 문제: 주요 Jenkins 업그레이드 후 보안 설정을 조정해야 하는 경우가 있습니다.
'액세스 거부' 및 권한 부여 오류 문제 해결
이러한 문제를 진단하고 해결하기 위한 체계적인 접근 방식을 살펴보겠습니다.
1단계: 인증 확인 (사용자가 알려져 있습니까?)
자격 증명 확인: 사용자 이름과 비밀번호가 올바른지 확인하십시오. 간단해 보이지만 종종 원인입니다.
알려진 정상 계정으로 테스트: 관리자 계정이 있으면 해당 계정으로 로그인해 보십시오. 관리자 계정이 작동하면 문제는 특정 사용자의 인증 또는 권한 부여에 있을 가능성이 높습니다. 관리자 계정도 실패하면 더 광범위한 보안 영역 문제를 나타냅니다.
보안 영역 구성 검토:
Jenkins 관리 > 전역 보안 구성으로 이동합니다.- Jenkins 자체 사용자 데이터베이스:
Jenkins 관리 > 사용자 관리에서 사용자가 존재하는지 확인합니다. - LDAP: LDAP 서버 URL, 관리자 DN, 관리자 비밀번호, 사용자 검색 기준을 확인합니다. Jenkins 서버가 LDAP 서버에 연결할 수 있는지 확인합니다(네트워크 연결 확인). 가능한 경우
LDAP 설정 테스트버튼을 확인합니다.
# 예: Jenkins 서버에서 LDAP 연결 테스트 (LDAP 서버/포트로 대체) nc -vz ldap.example.com 389- Jenkins 자체 사용자 데이터베이스:
2단계: 권한 부여 구성 확인 (사용자가 무엇을 할 수 있습니까?)
사용자가 인증되면 다음 단계는 올바른 권한이 있는지 확인하는 것입니다.
활성 권한 부여 전략 식별:
Jenkins 관리 > 전역 보안 구성으로 이동하여 선택된 권한 부여 전략을 확인합니다.매트릭스 기반 보안:
전역 보안 구성페이지에서 전역 권한 매트릭스를 확인합니다. 사용자 또는 사용자가 속한 그룹에 필요한 전역 권한(예:Overall/Read,Job/Read)이 있는지 확인합니다.- 프로젝트 기반 매트릭스 권한 부여가 활성화된 경우 개별 작업 구성을 확인하여 재정의가 있는지 확인합니다. 사용자에게 전역
Read권한이 있지만 특정 프로젝트에서 명시적으로 거부될 수 있습니다.
역할 기반 전략 플러그인:
Jenkins 관리 > 역할 관리 및 할당(또는 플러그인 버전에 따라 유사)으로 이동합니다.- 역할이 적절한 권한(예:
전역 역할,프로젝트 역할,폴더 역할)으로 정의되었는지 확인합니다. - 사용자가 올바른 역할에 할당되었는지 확인합니다.
팁: "Who Am I?" 링크 사용: 로그인한 후(제한된 액세스라도) 오른쪽 상단의 사용자 이름을 클릭한 다음 "Who Am I?"를 클릭합니다. 이 페이지에는 현재 사용자 세부 정보 및 권한이 나열되어 있어 디버깅에 매우 유용합니다.
3단계: Jenkins 시스템 로그 검토
Jenkins 로그는 내부에서 발생하는 상황에 대한 자세한 통찰력을 제공하는 최고의 도구입니다.
위치: Jenkins 로그는 일반적으로
$JENKINS_HOME/logs/jenkins.log에 있습니다.Jenkins 관리 > 시스템 로그를 통해 볼 수도 있습니다(권한이 있는 경우).검색 키워드:
Access Denied,authentication failed,authorization failure,permission denied,SecurityFilter,AuthenticationManager,AuthorizationStrategy를 찾습니다.# 예: 최근 Jenkins 로그에서 일반적인 보안 용어 검색 grep -Ei 'access denied|authentication|authorization|permission|crumb|csrf' "$JENKINS_HOME/logs/jenkins.log"
설정을 변경하기 전에 오류를 읽으십시오
정확한 텍스트가 중요합니다. anonymous is missing the Overall/Read permission은 일반적으로 Jenkins가 요청을 로그인한 사용자와 연결하지 않았음을 의미합니다. 이는 브라우저 세션이 만료되었거나, 리버스 프록시가 쿠키를 드롭했거나, API 토큰이 전송되지 않았거나, 스크립트가 잘못된 인증 방법을 사용한 경우 발생할 수 있습니다. Jenkins가 요청을 익명으로 보는 경우 사용자에게 더 많은 권한을 부여해도 도움이 되지 않습니다.
user is missing Job/Build는 인증은 작동했지만 권한 부여가 실패했음을 의미합니다. 이 경우 권한 부여 전략, 폴더 권한, 프로젝트 매트릭스 설정 및 역할 할당을 확인하십시오. 폴더 기반 Jenkins 설정의 경우 먼저 폴더를 확인하십시오. 사용자에게 전역 읽기 액세스 권한이 있어도 한 폴더 내에서는 권한이 부족할 수 있습니다.
No valid crumb was included in the request는 CSRF 보호를 가리킵니다. 이는 사용자 이름과 비밀번호만 사용하여 Jenkins에 POST하는 스크립트에서 일반적입니다. 최신 자동화는 일반적으로 API 토큰을 사용하고 /crumbIssuer/api/json에서 crumb을 가져오거나 crumb을 올바르게 처리하는 클라이언트/라이브러리를 사용해야 합니다. 하나의 스크립트를 작동시키기 위해 CSRF 보호를 비활성화하지 마십시오.
플러그인 업그레이드 후 Access Denied는 종종 플러그인이 이전보다 더 구체적인 권한을 확인하기 시작했거나 UI 링크가 다른 권한으로 보호되는 페이지로 이동했음을 의미합니다. 업그레이드와 시기가 일치하면 플러그인 변경 로그를 검토하십시오. 매트릭스 보안에서 역할 기반 보안으로 전환한 후 문제가 시작된 경우 역할 이름이 동일한 것을 의미한다고 가정하지 말고 이전 권한을 새 역할과 하나씩 비교하십시오.
안전한 문제 해결 순서
정상적인 브라우저 로그인으로 시작하십시오. 이전 쿠키가 테스트를 혼동하지 않도록 개인 창을 사용하십시오. 사용자가 로그인할 수 없으면 보안 영역(로컬 Jenkins 사용자 데이터베이스, LDAP, Active Directory, SAML, OAuth 또는 구성된 공급자)에 집중하십시오. 사용자 이름 형식이 변경되었는지 확인하십시오. 일부 ID 공급자는 jane을 보내고, 일부는 [email protected]을 보내며, 일부는 사용자가 입력하는 사용자 이름처럼 보이지 않는 안정적인 ID를 보냅니다.
로그인이 작동하면 사용자의 프로필과 가능한 경우 "Who Am I?" 페이지를 엽니다. Jenkins가 보는 사용자 ID 및 그룹 이름을 확인하십시오. 이는 그룹 구성원이 ID 팀이 예상하는 것과 일치하지 않을 수 있는 LDAP 및 SSO에서 특히 유용합니다. 누락된 그룹 매핑은 많은 사용자로부터 한 번에 권한을 제거할 수 있습니다.
다음으로 알려진 관리자 계정으로 테스트하십시오. 관리자가 작업을 수행할 수 있으면 인스턴스는 정상이며 영향을 받는 사용자에게 권한이 없는 것입니다. 관리자도 실패하면 더 광범위한 구성 문제, 플러그인 오류, 리버스 프록시 문제 또는 손상된 crumb/세션 동작을 찾으십시오.
그런 다음 가장 작은 영향을 받는 개체를 확인하십시오. 사용자가 하나의 작업을 빌드할 수 없으면 전역 보안을 변경하는 것으로 시작하지 마십시오. 해당 작업, 해당 폴더, 상속된 권한, 역할 패턴 및 프로젝트 기반 매트릭스 항목을 확인하십시오. team-a/.*와 같은 역할 패턴은 정규식이 대소문자를 구분하거나 너무 좁게 작성된 경우 Team-A/service-api와 같은 이름이 변경된 폴더와 일치하지 않습니다.
API 토큰, Crumb 및 자동화 실패
많은 Jenkins 보안 사고는 인간의 로그인 문제가 아닙니다. 이전에는 작동했지만 지금은 실패하는 스크립트입니다. 가장 먼저 확인해야 할 것은 스크립트가 실제 비밀번호 대신 API 토큰을 사용하고 있는지 여부입니다. API 토큰은 교체하기 쉽고 운영적으로 범위를 지정하기에 더 안전합니다.
간단한 요청은 다음과 같을 수 있습니다:
curl -u "deploy-bot:${JENKINS_TOKEN}" \
"https://jenkins.example.com/job/service-api/build?token=unused"
crumb이 필요한 POST 요청의 경우 먼저 가져옵니다:
CRUMB=$(curl -s -u "deploy-bot:${JENKINS_TOKEN}" \
"https://jenkins.example.com/crumbIssuer/api/json" |
jq -r '.crumbRequestField + ":" + .crumb')
curl -X POST -u "deploy-bot:${JENKINS_TOKEN}" \
-H "$CRUMB" \
"https://jenkins.example.com/job/service-api/build"
일부 Jenkins 구성은 API 토큰으로 인증된 요청을 crumb 검사에서 면제하는 반면, 다른 구성은 버전 및 플러그인에 따라 여전히 crumb이 필요합니다. 다른 환경의 가정을 복사하지 말고 인스턴스에 대해 테스트하십시오.
서비스 계정의 경우 자동화에 필요한 권한만 부여하십시오. 배포 트리거는 한 폴더에 Job/Build가 필요할 수 있습니다. Overall/Administer는 필요하지 않을 것입니다. 동일한 토큰이 10개의 관련 없는 스크립트에서 사용되는 경우 별도의 서비스 사용자로 분할하여 모든 것을 중단하지 않고 하나를 교체하거나 비활성화할 수 있습니다.
Jenkins 보안처럼 보이는 리버스 프록시 문제
Jenkins가 Nginx, Apache, 로드 밸런서 또는 인그레스 컨트롤러 뒤에 있는 경우 세션 및 crumb 오류는 프록시 계층에서 발생할 수 있습니다. Jenkins가 올바른 외부 URL, 체계, 호스트 및 헤더를 수신하는지 확인하십시오. 일반적인 증상은 로그인이 한 페이지에서 작동하고 다음 페이지에서 실패하는 것입니다. 이는 쿠키가 잘못된 호스트로 범위가 지정되거나 Jenkins가 요청이 HTTP라고 생각하지만 브라우저가 HTTPS를 사용하기 때문입니다.
Jenkins 관리 > 시스템에서 Jenkins URL을 검토하십시오. 사용자가 실제로 여는 URL과 일치해야 합니다. 프록시의 경우 X-Forwarded-Proto 및 X-Forwarded-Host와 같은 헤더가 올바르게 전달되는지 확인하십시오. WebSocket 또는 에이전트 연결이 관련된 경우 브라우저 로그인과 별도로 해당 경로를 확인하십시오.
로드 밸런싱된 컨트롤러는 특별한 경고 신호입니다. 일반 Jenkins 컨트롤러는 상태 저장입니다. 여러 개의 독립적인 Jenkins 컨트롤러를 하나의 URL 뒤에 두고 세션, 대기열 상태 및 작업 상태가 상태 비저장 웹 앱처럼 작동할 것으로 기대하지 마십시오. Jenkins의 고가용성에는 일반 라운드 로빈 로드 밸런서가 아닌 이를 위해 설계된 제품 또는 아키텍처가 필요합니다.
인스턴스를 악화시키지 않고 긴급 액세스
모든 사람이 잠겨 있으면 파일을 편집하기 전에 잠시 멈추십시오. 가능하면 먼저 $JENKINS_HOME의 백업 또는 스냅샷을 만드십시오. 보안 구성은 XML 파일에 저장되며, 서두른 편집은 복구를 더 어렵게 만들 수 있습니다.
일반적인 비상 경로는 config.xml에서 보안을 일시적으로 비활성화하고, Jenkins를 다시 시작하고, 액세스를 다시 얻고, UI에서 보안 설정을 수정한 다음 즉시 보안을 다시 활성화하는 것입니다. 이는 일상적인 해결 방법이 아닌 긴급 조치로 취급해야 합니다. 보안이 비활성화된 동안 네트워크 액세스를 제한하십시오. 변경된 사항을 기록하십시오. 인시던트 중에 노출되었을 수 있는 자격 증명을 교체하십시오.
Configuration as Code를 사용하는 경우 UI를 패치하고 소스 파일을 잊지 마십시오. 다음 리로드로 수정 사항이 취소될 수 있습니다. CasC YAML을 업데이트하고, 검토하고, 액세스가 복원되면 정상적인 프로세스를 통해 적용하십시오.
반복 잠금 방지
가급적 다른 복구 경로로 지원되는 두 개 이상의 인간 관리자 계정 또는 그룹을 유지하십시오. 모든 관리자가 하나의 SSO 그룹에 의존하고 해당 그룹 매핑이 중단되면 아무도 UI에서 Jenkins를 수정할 수 없습니다.
권한 부여 모델을 일반 언어로 문서화하십시오. "개발자는 해당 폴더에서 작업을 읽고 빌드할 수 있습니다. 릴리스 엔지니어는 배포 작업을 구성할 수 있습니다. 플랫폼 관리자는 Jenkins를 관리합니다." 이는 수백 개의 확인란이 있는 매트릭스 스크린샷보다 더 유용합니다.
폴더 이동, 플러그인 변경, SSO 변경 및 Jenkins 업그레이드 후 권한을 검토하십시오. 보안 문제는 종종 무해해 보이는 이름 변경 또는 ID 공급자 정리 후에 나타납니다.
마지막으로 이전 자격 증명을 삭제하기 전에 서비스 계정 토큰을 테스트하십시오. 주요 자동화 계정을 확인하는 짧은 감사 스크립트는 배포 창을 절약할 수 있습니다. 중단이 로그인, 권한 평가, 요청 보호 또는 Jenkins 앞의 프록시에서 발생했는지 알면 보안 문제 해결이 훨씬 쉬워집니다.