그래픽 Terminal에서는 서명이 성공하지만 Jenkins Job에서 errSecInternalComponent이 반환됩니다.
가장 빠른 해결법은 인증서를 먼저 다시 설치하는 것이 아닙니다. 같은 macOS 계정과 같은 서명 신원으로 그래픽 로그인 Terminal, SSH, Jenkins Job에서 최소 codesign 테스트를 실행한 뒤 디지털 신원, Keychain 접근, Agent 보안 맥락을 차례로 비교해야 합니다.
[ SECTION_01 ] 이 문서가 필요한 담당자
Jenkins Mac Agent와 iOS 또는 macOS 배포 파이프라인을 운영하는 플랫폼 엔지니어가 대상입니다. 인증서 개인 키, Keychain 권한, 배포 감사 기록을 관리하는 기업 보안 담당자에게도 적용됩니다.
원격 Mac이 무인 서명과 장애 복구를 감당할 수 있는지 평가하는 IT 구매 담당자라면 마지막 복구 승인 기준까지 확인해야 합니다.
마지막 업데이트: 2026년 9월 5일. Apple 개발자 문서와 Apple 기술 지원 게시물, Jenkins 공식 Agent 문서를 기준으로 내용을 재검토했습니다. Apple의 관련 문제 해결 게시물은 2026년 7월 6일에 최근 명시적으로 수정된 것으로 확인됩니다. Apple 코드 서명 지원 주제와 코드 서명 인증서 내부 구조 문서를 함께 확인해야 합니다.
[ SECTION_02 ] 먼저 분리해야 할 다섯 가지 지표
errSecInternalComponent은 한 가지 원인만 가리키는 오류가 아닙니다. 인증서가 보인다는 사실과 서명에 사용할 수 있는 완전한 디지털 신원이 존재한다는 사실도 다릅니다. Apple은 SSH와 CI 같은 비표준 서명 환경에서 Keychain 잠금, 개인 키 접근 제어, 인증서 신뢰, 혼합 보안 맥락을 함께 확인하도록 안내합니다. Apple의 코드 서명 일반 안내를 근거로 다음처럼 분리합니다.
| 진단 지표 | 확인할 사실 | 실패할 때 우선 의심할 원인 | 판정 점수 |
|---|---|---|---|
| 디지털 신원 | 인증서와 대응 개인 키가 한 쌍으로 존재하는지 | 개인 키 누락, 만료, 잘못된 팀 신원 | 0~2 |
| Keychain 접근 | 실제 Keychain, 잠금 상태, 검색 범위, 접근 제어 | 잠긴 Keychain, 잘못된 검색 목록, ACL 거부 | 0~2 |
| 실행 맥락 | macOS 사용자, HOME, 프로세스 소유자, Agent 시작 방식 |
SSH와 Jenkins의 보안 세션 불일치 | 0~2 |
| 서명 격리 | 일반 빌드와 배포 서명이 같은 노드를 쓰는지 | 생산 개인 키의 과도한 노출 | 0~2 |
| 복구 능력 | 재시작 후 무인 서명이 다시 되는지 | 수동 잠금 해제나 팝업 의존 | 0~2 |
각 항목에서 2점을 얻어도 생산 승인으로 바로 이어지지는 않습니다. 특히 복구 능력과 서명 격리는 별도 차단 조건으로 취급해야 합니다.
[ SECTION_03 ] 디지털 신원 지표: 인증서가 보이는 것만으로는 부족합니다
Jenkins가 컴파일은 완료하지만 codesign에서 실패한다면, 먼저 유효한 서명 신원을 확인해야 합니다. 인증서 목록에 이름이 보이는지보다 중요한 것은 해당 인증서에 대응하는 개인 키를 같은 macOS 계정이 실제로 사용할 수 있는지입니다.
검증은 생산 인증서가 아닌 격리된 시험 인증서와 시험 파일로 진행합니다.
security find-identity -v -p codesigning
security find-certificate -a
codesign -s "시험 서명 신원" --force --timestamp=none ./Test.app
find-identity 결과가 없거나 유효하지 않은 신원으로 표시되면 인증서를 반복해서 가져오지 않아야 합니다. 다음 증거를 표에 기록합니다.
| 관찰 결과 | 의미 | 다음 확인 |
|---|---|---|
| 인증서와 개인 키가 모두 존재 | 신원 후보가 있음 | Keychain 잠금과 접근 제어 확인 |
| 인증서만 존재 | 서명 가능한 신원이 아님 | 대응 개인 키와 가져오기 경로 확인 |
| 신원이 만료 또는 무효 | 현재 배포에 사용할 수 없음 | 새 인증서 발급 및 신뢰 체인 확인 |
| 그래픽 Terminal만 성공 | 호스트 전체 문제보다 세션 차이 가능성 | SSH와 Jenkins 맥락 비교 |
| 모든 환경에서 실패 | 사용자 세션보다 신원 또는 파일 문제 가능성 | 시험 파일과 인증서 체인 재검증 |
Apple의 인증서와 디지털 신원 구조 설명은 인증서, 개인 키, 서명 신원을 같은 개념으로 취급하지 않도록 구분합니다. 이 구분 없이 인증서만 재설치하면 원인 기록이 사라질 수 있습니다.
인증서가 Keychain에 보이는데도 Jenkins가 서명하지 못하는 경우
그래픽 Keychain 화면에서 인증서가 보이더라도 Jenkins가 사용하는 Keychain이 다를 수 있습니다. 인증서와 개인 키가 다른 Keychain에 있거나, 개인 키의 접근 제어가 Jenkins의 서명 도구를 허용하지 않을 수도 있습니다.
따라서 화면 캡처보다 Jenkins Job 내부에서 실제 경로와 신원을 출력하는 편이 정확합니다. 단, 개인 키 비밀번호와 인증서 원문은 출력하지 않아야 합니다.
[ SECTION_04 ] Keychain 접근성 지표: 잠금, 검색 범위, ACL을 분리합니다
그래픽 로그인은 사용자의 Keychain이 자동으로 열릴 수 있습니다. 반면 SSH 세션은 같은 Unix 사용자로 접속해도 동일한 대화형 보안 세션이나 자동 잠금 해제 상태를 보장하지 않습니다. 이 차이 때문에 SSH에서는 실패하고 그래픽 Terminal에서는 성공할 수 있습니다.
SSH와 Jenkins에서 다음 최소 항목을 비교합니다.
id
printf '%s\n' "$HOME"
security list-keychains
security default-keychain
security show-keychain-info "$HOME/Library/Keychains/login.keychain-db"
Keychain 비밀번호를 명령 인자, Jenkinsfile, 일반 환경 변수에 넣으면 안 됩니다. 로그에 남은 비밀값은 오류 수정 전에 먼저 폐기하고 교체해야 합니다.
개인 키 접근 제어를 조정할 때는 모든 실행 파일을 허용하는 방식보다 실제 서명에 필요한 도구로 범위를 제한해야 합니다. codesign이 무인 환경에서 팝업 없이 개인 키를 사용할 수 있는지 시험하고, 변경 전후의 접근 제어 목록을 감사 기록에 남깁니다.
Apple의 코드 서명 관련 기술 문서는 인증서 신뢰와 개인 키 사용 가능성을 별도로 다룹니다. 따라서 “인증서가 보인다”는 결과만으로 Keychain 문제를 종료해서는 안 됩니다.
SSH 환경에서 errSecInternalComponent을 해소하는 판단 기준
SSH에서 실패할 때는 먼저 Keychain 잠금과 검색 범위를 확인합니다. 그 다음 같은 계정으로 비대화형 codesign을 실행합니다. 그래픽 Terminal, SSH, Jenkins가 모두 같은 계정과 같은 시험 파일을 사용해야 비교가 성립합니다.
SSH만 실패하면 계정 자체를 바꾸기보다 다음 세 가지를 기록합니다.
- SSH 세션의
HOME과 실제 Keychain 경로 - Keychain 잠금 상태와 기본 검색 목록
- 개인 키가 서명 도구의 무인 접근을 허용하는지 여부
sudo 또는 root 전환은 일반적인 해결책이 아닙니다. 사용자와 HOME, Keychain 위치가 바뀌어 증거를 오히려 흐릴 수 있고, 생산 개인 키의 접근 범위도 넓어질 수 있습니다.
[ SECTION_05 ] 실행 맥락 지표: Jenkins Agent의 사용자를 별도로 검증합니다
Jenkins Controller의 자격 증명과 macOS 로컬 서명 신원은 서로 다른 계층입니다. Controller에 저장된 자격 증명이 있다고 해서 Mac의 Keychain 개인 키 접근 권한이 자동으로 생기지는 않습니다.
Jenkins Job에서 다음 값을 기록하되 비밀값은 제외합니다.
id
printf '%s\n' "$HOME"
ps -p "$$" -o user=,pid=,command=
security find-identity -v -p codesigning
확인 기준은 간단합니다. Job 실행자와 그래픽 또는 SSH에서 시험한 사용자가 같은지, Agent 프로세스의 소유자와 HOME이 같은지, Agent가 어떤 방식으로 시작됐는지를 비교합니다.
Jenkins 공식 문서는 노드와 실행 라벨 관리에서 특정 작업을 특정 노드에 배치하는 경계를 설명합니다. 또한 Agent 실행 방식 안내를 기준으로 Agent 연결 계정과 프로세스 상태를 기록해야 합니다.
Jenkins가 컴파일은 하지만 codesign에서만 실패하는 이유
컴파일은 인증서 개인 키에 접근하지 않아도 완료될 수 있습니다. 반면 codesign은 서명 신원 검색, 개인 키 접근, 인증서 신뢰, Keychain 상태를 모두 요구합니다.
따라서 컴파일 성공은 Mac Agent가 정상이라는 증거가 아닙니다. 최소 서명 테스트가 실패하면 배포 파이프라인 전체를 재시도하지 말고, 먼저 위 세 실행 맥락의 결과를 비교해야 합니다.
[ SECTION_06 ] 서명 격리 지표: 모든 Job이 생산 개인 키를 보지 않게 합니다
일반 PR 빌드, 아카이브 생성, 공식 배포 서명은 같은 권한으로 운영하지 않는 편이 안전합니다.
- 일반 PR 빌드: 서명하지 않거나 시험 신원만 사용합니다.
- 아카이브 작업: 제한된 노드와 제한된 자격 증명을 사용합니다.
- 공식 배포: 전용 서명 계정과 전용 노드에서만 실행합니다.
전용 임시 Keychain은 짧은 검증이나 격리된 아카이브에 적합합니다. 로그인 Keychain은 운영 편의성이 있지만 사용자 세션과 잠금 상태에 의존할 수 있습니다. 전용 배포 노드는 비용과 운영 책임이 늘지만 생산 개인 키의 노출 범위를 가장 명확하게 제한합니다.
| 운영 선택 | 적합한 작업 | 장점 | 차단 조건 |
|---|---|---|---|
| 로그인 Keychain | 개발용 또는 제한된 내부 빌드 | 설정이 단순함 | 무인 재시작에서 잠금 상태가 달라짐 |
| 임시 Keychain | 시험 서명, 단기 아카이브 | 작업별 격리가 쉬움 | 인증서 주입과 삭제 검증이 필요함 |
| 전용 배포 노드 | 공식 App 배포와 복구 | 계정, 라벨, 감사 범위가 명확함 | 물리 또는 원격 노드 운영 책임이 필요함 |
Jenkins 라벨은 단순한 예약 기능이 아닙니다. 어떤 Job이 생산 개인 키를 가진 노드에 도달할 수 있는지 통제하는 정책 경계입니다. Job 권한, 노드 라벨, 자격 증명 사용 기록에는 실행자, 대상 노드, 시작과 종료 시각, 결과, 정리 완료 여부가 남아야 합니다.
작업 종료 후에는 작업 공간, 임시 인증서 파일, 임시 Keychain, 로그 내 비밀값을 점검합니다. 삭제 명령을 실행했다는 사실만 기록하지 말고 삭제 후 다시 찾을 수 없는지 확인해야 합니다.
[ SECTION_07 ] 첫 번째 승인 기준: 최소 서명 결과를 세 환경에서 맞춥니다
다음 순서 자체가 본문의 구조는 아니며, 각 지표를 검증하기 위한 반복 절차입니다.
- 격리 테스트 계정과 시험 인증서, 시험 앱을 준비합니다.
- 그래픽 로그인 Terminal에서
codesign결과와 서명 신원을 저장합니다. - 같은 macOS 계정으로 SSH에 접속해 Keychain 경로와 잠금 상태를 기록합니다.
- 같은 계정으로 실행되는 Jenkins Job에서
HOME, 프로세스 소유자, 신원 목록을 기록합니다. - 세 결과에서 인증서 이름, 개인 키 사용 가능성, 오류 메시지를 비교합니다.
- 하나의 지표만 변경하고 최소 서명 테스트를 다시 실행합니다.
- 변경 전후 로그와 접근 제어 상태를 함께 보관합니다.
한 번에 인증서, Keychain, Agent 서비스를 모두 바꾸면 어떤 조치가 효과가 있었는지 입증할 수 없습니다. 기업 운영에서는 복구보다 원인 재현성과 변경 추적성이 더 중요합니다.
[ SECTION_08 ] 재시작 복구 지표: 사람이 팝업을 누르면 생산 승인이 아닙니다
Jenkins Agent 재시작 뒤 서명을 자동 복구하려면 세 가지 조건을 따로 시험해야 합니다.
- Mac 호스트 재시작 뒤 Agent가 다시 연결되는지 확인합니다.
- Agent 재연결 뒤 Keychain이 필요한 상태로 준비되는지 확인합니다.
- 그래픽 로그인 없이 최소 서명과 실제 아카이브가 완료되는지 확인합니다.
이 시험에서는 사람이 Keychain 팝업을 클릭하지 않아야 합니다. 수동 조작이 필요하다면 해당 노드는 무인 공식 배포 노드로 승인하지 않습니다.
복구 승인 기록에는 다음 항목이 포함되어야 합니다.
- 최초 실패 로그와 실패한 실행 맥락
- 변경한 신원, Keychain 또는 ACL
- 무인 최소 서명 결과
- 재시작 후 Agent 연결 결과
- 재시작 후 실제 아카이브 결과
- 작업 공간과 인증서 자료의 정리 결과
- 실패 시 원격 접근과 롤백 방법
현재 물리 Mac을 운영 중이라면 Mac 미니 대여 가격 안내와 같은 비용 자료를 확인하더라도, 가격보다 먼저 위 복구 증거를 확보해야 합니다. 원격 노드를 검토할 때는 NOVAKVM의 원격 Mac 접근 경로에서 그래픽 접근과 SSH 운영 가능 여부를 확인한 뒤 격리 시험을 진행하는 편이 안전합니다.
[ SECTION_09 ] 오류 원인별 최종 판정
다섯 지표의 결과를 다음처럼 해석하면 불필요한 재설치를 줄일 수 있습니다.
- 인증서만 보이고
find-identity가 유효한 신원을 만들지 못하면 디지털 신원 문제입니다. - 신원은 유효하지만 SSH와 Jenkins에서만 실패하면 Keychain 잠금, 검색 범위 또는 ACL을 먼저 봅니다.
- SSH는 성공하고 Jenkins만 실패하면 Agent 사용자,
HOME, 시작 방식, 프로세스 보안 맥락을 비교합니다. - 시험 서명은 성공하지만 공식 배포만 실패하면 배포 인증서, 접근 정책, 전용 노드 라벨을 확인합니다.
- 재시작 뒤 사람의 조작이 필요하면 복구 능력 지표가 실패한 것입니다.
최종 점수는 운영 판단을 돕는 내부 도구로 사용합니다. 디지털 신원, Keychain 접근, 실행 맥락, 격리성, 복구성에서 각각 2점을 얻는 구조가 이상적이지만, 복구성 0점이면 공식 무인 배포 승인을 보류해야 합니다.
[ SECTION_10 ] 기존 장비와 원격 Mac을 비교하는 마지막 기준
현재 장비에서 인증서 재설치만 반복하면 원인은 남지 않고, 로그인 세션에 의존하며, 재시작 뒤 수동 복구가 필요하고, 생산 개인 키가 일반 Job에 노출될 수 있습니다. 특히 물리 장비를 여러 팀이 공유하면 접근 기록과 작업별 격리를 별도로 구현해야 합니다.
반대로 원격 Mac을 선택하더라도 모든 작업을 한 노드에 몰아서는 안 됩니다. 전용 비 root 서명 계정, Jenkins 라벨, SSH와 그래픽 접근, 재시작 복구 시험을 갖춘 격리 노드로 먼저 검증해야 합니다. 기존 장비가 배포 창 안에 격리 시험을 완료하지 못한다면, NOVAKVM의 Mac을 단기 독립 서명 검증 노드로 사용해 같은 증거표를 채우는 방식이 더 안전합니다. 장기 고정 부하나 물리 인터페이스가 반드시 필요한 조직이라면 직접 구매가 더 적합할 수 있습니다.
핵심은 errSecInternalComponent을 인증서 설치 문제로 단정하지 않는 것입니다. 세 실행 환경의 최소 서명 결과를 맞추고, Keychain과 Agent 맥락을 분리한 뒤, 재시작 후 무인 복구까지 통과한 노드만 생산 배포에 투입해야 합니다.