"CMD+K는 더 이상 안 물어봤어. 근데 설정을 열 때마다 여전히 매번 물어봤어."
Mac에서 비밀은 어디에 두냐면
오래 보관해야 하는 비밀이 있는 앱은 그걸 Security 프레임워크의 SecItem API로 키체인에 저장해. 가족 앱들도 집에 있는 엔진에 접속하려고 PIN을 들고 있어. 파일이나 UserDefaults엔 절대 안 둬. Mac엔 알아둬야 할 키체인이 둘이야. 로그인 키체인(파일 기반)은 항목마다 접근 제어 목록이 있고, 그 목록이 코드 requirement로 특정 앱을 신뢰해. 데이터 보호 키체인(kSecUseDataProtectionKeychain)은 iOS처럼 키체인 접근 그룹 엔타이틀먼트로 접근 범위를 정해. 그래서 서명 안 됐거나 엔타이틀먼트 없는 바이너리는 항목 대신 -34018(errSecMissingEntitlement)을 받아.
다시 서명해도 사라지지 않은 권한 창
키체인을 읽을 때마다 권한을 묻지 않게 하려고, 가족 편집기를 애드혹 서명에서 안정적인 자체 서명 신원으로 옮겼어. 한 경로는 조용해졌는데, 다른 경로(열 때마다 PIN을 다시 읽는 설정 탭)는 읽을 때마다 계속 물어봤어. requirement는 안정적인 걸 확인했고, 코드도 멀쩡했어.
문제는 항목 자체였어. 그 항목들은 옛 애드혹 빌드가 만든 거라서, 접근 목록이 이제 세상에 없는 코드 requirement를 믿고 있었어. 그 항목들 입장에서 새로 서명한 앱은 영원히 남이었던 거지. 빠른 경로가 고쳐진 것처럼 보인 건 첫 잠금 해제 뒤에 세션 토큰을 메모리에 캐시하고 키체인을 다시 안 읽었기 때문이야. "항상 허용"을 누르지 않고 확실하게 고치는 방법은 그 서비스의 항목을 전부 지우고, 서명된 앱이 새로 저장하게 하는 거야. 그러면 그 앱이 항목의 주인이 돼서 묻지 않고 읽어.
지우는 건 각 Mac의 콘솔 세션에서 직접 해야 해. ssh에선 로그인 키체인이 "User interaction is not allowed"라고 대답해. 원격 세션은 GUI 로그인 바깥이라 거기선 키체인이 접근 권한 창을 못 띄우고, ssh에서 키체인을 풀려면 계정 비밀번호를 스크립트에 넘겨야 해. 다음 트랙에서 다룰, ssh로 서명이 실패하는 문제도 같은 이유야.
없음, 잠김, 못 씀은 서로 다른 대답이야
키체인 읽기 실패를 전부 "저장된 PIN 없음"으로 처리하면 문제가 생겨. 키체인이 잠겼을 뿐인데 첫 실행 화면이 뜨고, 엔타이틀먼트가 빠졌을 뿐인데 조용히 초기화돼 버려. 가족의 공유 비밀 저장소는 결과를 셋으로 나눠 돌려주고, 호출하는 쪽은 각각 다르게 보여줘. 없음이면 PIN을 입력하라고 하고, 잠김이면 키체인이 잠겼다고(아니면 세션이 UI를 못 띄운다고) 말하고, 못 씀이면 상태 코드를 보여줘.