| 메시지 | 원인 |
|---|---|
Improper format of Kerberos configuration file |
krb5.conf 문법 오류. 괄호 · 들여쓰기 · 잘린 줄 |
Cannot find KDC for realm |
realm 에 대한 KDC 주소를 모름. [realms] 누락 또는 DNS SRV 실패 |
Cannot determine realm for host |
호스트 이름에서 realm 을 유추하지 못함. [domain_realm] 누락 |
Preauthentication failed |
비밀번호 · keytab 키 불일치, 또는 시계 오차 |
Clock skew too great |
클라이언트와 KDC 의 시각 차이가 허용치를 넘음 |
Ticket expired / GSS API error ... ticket expired |
티켓 유효기간 만료. 갱신 필요 |
Client not found in Kerberos database |
프린시펄이 KDC 에 없음. 철자 · realm 대소문자 확인 |
Server not found in Kerberos database |
서비스 프린시펄 없음. FQDN · 역방향 조회 문제인 경우가 많다 |
Key version number for principal ... is incorrect |
keytab 과 KDC 의 kvno 불일치. keytab 재배포 필요 |
no supported default etypes |
암호화 유형 불일치 - 별도 문서 |
[libdefaults]
default_realm = EXAMPLE.COM
dns_lookup_realm = false
dns_lookup_kdc = false
rdns = false
ticket_lifetime = 24h
renew_lifetime = 7d
[realms]
EXAMPLE.COM = {
kdc = kdc1.example.com
kdc = kdc2.example.com
admin_server = kdc1.example.com
}
[domain_realm]
.example.com = EXAMPLE.COM
example.com = EXAMPLE.COM
realm 이름은 관례상 대문자이며 대소문자를 구분한다. example.com 과 EXAMPLE.COM 은 다른 realm 이다.
[domain_realm] 에서 점으로 시작하는 줄은 하위 도메인 전체, 점이 없는 줄은 그 이름 자체에 대응한다. 둘 다 있어야 host.example.com 과 example.com 이 모두 매핑된다.
rdns 를 켜 두면 서비스 호스트 이름을 역방향 조회로 정규화한다. 역방향 영역이 없거나 틀린 환경에서는 Server not found in Kerberos database 의 원인이 되므로 끄는 편이 안전하다.
파일 권한도 본다. 서비스 계정이 읽지 못하면 "설정이 없는" 것과 같다.
ls -l /etc/krb5.conf # 644, root:root
klist -k /path/to.keytab # keytab 은 600 이며 서비스 계정 소유여야 한다
Kerberos 는 재전송 공격을 막으려고 타임스탬프를 쓴다. 기본 허용 오차는 5분이며 넘으면 Preauthentication failed 또는 Clock skew too great 가 난다.
chronyc tracking
timedatectl status
허용치를 늘리는 clockskew 설정은 임시방편이다. NTP 를 맞추는 것이 정답이다. 가상 머신이 스냅숏에서 복원됐거나 호스트 시각과 어긋난 경우가 흔하다.
klist # 남은 시간 확인
kinit <principal> # 새로 받기
kinit -R # 갱신 가능 기간 안이면 연장
kinit -kt /path/to.keytab <principal>
realm join · distcp 처럼 오래 도는 작업이 중간에 ticket expired 로 죽는다면, 시작 전에 티켓을 새로 받고 renew_lifetime 을 충분히 잡는다. 배치 · 서비스는 비밀번호 대신 keytab 으로 인증해 사람이 개입하지 않게 한다.
No credentials cache found 는 티켓이 아예 없다는 뜻이다. 서비스 계정으로 전환(su - kafka)한 뒤 klist 해 보면 계정마다 캐시가 다르다는 것을 알 수 있다. 캐시 위치는 KRB5CCNAME 이 정하며, 최근 배포판은 파일 대신 KEYRING · KCM 을 쓴다. 자세한 것은 Kerberos 티켓 캐시 - KCM 과 FILE 에 있다.
Kafka · Atlas · HBase 클라이언트가 다음과 같은 메시지를 낸다.
Could not login: the client is being asked for a password, but the Kafka client
code does not currently support obtaining a password from the user.
사람이 입력할 수 없는 프로세스인데 비밀번호 인증 경로로 들어갔다는 뜻이다. 원인은 셋 중 하나다.
useTicketCache=true)인데 캐시가 비어 있다.# kafka_client_jaas.conf
KafkaClient {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=true
storeKey=true
keyTab="/etc/security/keytabs/kafka.service.keytab"
principal="kafka/host.example.com@EXAMPLE.COM"
useTicketCache=false;
};
# 클라이언트 속성
security.protocol=SASL_PLAINTEXT
sasl.mechanism=GSSAPI
sasl.kerberos.service.name=kafka
# JVM 에 JAAS 파일과 krb5.conf 위치를 알린다
export KAFKA_OPTS="-Djava.security.auth.login.config=/etc/kafka/kafka_client_jaas.conf \
-Djava.security.krb5.conf=/etc/krb5.conf"
principal 의 호스트 부분은 그 노드의 FQDN 과 정확히 같아야 한다. _HOST 자리표시자를 쓰는 제품은 hostname -f 결과로 치환하므로, 짧은 이름만 나오면 치환이 어긋난다.
# 라이브러리 수준 추적. 어떤 KDC 에 무엇을 요청했는지 전부 보인다
KRB5_TRACE=/dev/stderr kinit -kt /path/to.keytab <principal>
# 자바 쪽
java -Dsun.security.krb5.debug=true -Djava.security.debug=gssloginconfig,configfile ...
KDC 쪽 로그(/var/log/krb5kdc.log)에는 어떤 프린시펄이 무슨 이유로 거절됐는지가 남는다. 클라이언트 메시지가 모호할 때는 KDC 로그가 더 정확하다.
no supported default etypes 계열.