Kerberos 로 보호된 HTTP 서비스(WebHDFS · HttpFS · YARN · Solr · 사내 웹 API)는 SPNEGO 로 인증한다. 서버가 WWW-Authenticate: Negotiate 를 보내면 클라이언트가 서비스 티켓을 붙여 다시 요청하는 방식이다.
curl 은 --negotiate 옵션으로 이 과정을 처리한다. 티켓은 curl 이 만들지 않으므로 호출 전에 유효한 티켓이 있어야 한다.
kinit <principal>
klist
curl -i --negotiate -u : "https://nn.example.com:9871/webhdfs/v1/user/haedong?op=LISTSTATUS"
--negotiate : SPNEGO 사용.-u : : 사용자 이름 · 비밀번호는 비운다. 이 인자가 없으면 curl 이 인증 헤더를 붙이지 않는다.-i : 응답 헤더를 함께 본다. 401 에서 200 으로 넘어가는 과정을 확인할 수 있다.curl 이 Kerberos 를 지원하는 빌드인지 먼저 확인한다.
curl -V | grep -i -E 'GSS|SPNEGO|Kerberos'
GSS-API · SPNEGO 가 없으면 옵션을 줘도 동작하지 않는다.
WebHDFS 의 쓰기 연산은 NameNode 가 DataNode 주소로 리다이렉트한 뒤 실제 전송이 일어난다. 따라서 -L 로 리다이렉트를 따라가야 한다.
curl -i -L --negotiate -u : -X PUT \
-T ./data.csv \
"https://nn.example.com:9871/webhdfs/v1/user/haedong/data.csv?op=CREATE&overwrite=true"
리다이렉트된 DataNode 주소는 클라이언트가 직접 접근할 수 있어야 한다. 컨테이너나 사외망에서 호출할 때 첫 요청은 되는데 전송에서 멈춘다면 대개 이 주소가 내부 이름이라 풀리지 않는 것이다. 이름 문제라면 dfs.client.use.datanode.hostname 설정과 DNS · hosts 를 함께 본다.
HttpFS 는 단일 게이트웨이로 동작해 리다이렉트가 없다. 포트만 다르고 경로는 같다.
curl -i --negotiate -u : -X PUT -T ./data.csv \
"https://httpfs.example.com:14000/webhdfs/v1/user/haedong/data.csv?op=CREATE&overwrite=true"
HTTP/1.1 401 Authentication required 만 반복: 티켓이 없거나 만료됐다. klist 로 확인하고 kinit 한다. 서비스 계정으로 도는 스크립트라면 keytab 으로 받는다.GSSAPI ... Server not found in Kerberos database: 접속한 호스트 이름의 HTTP/<FQDN> 프린시펄이 없다. IP 나 짧은 이름으로 접속하면 이 오류가 난다. 인증서와 마찬가지로 SPNEGO 도 FQDN 이 기준이다.-k 로 인증서 검증을 끄면 되는 경우: 인증 문제가 아니라 TLS 신뢰 문제다. 시험 단계에서만 쓰고 CA 를 등록해 해결한다.no_proxy 에 사내 도메인을 넣지 않으면 프록시가 인증 헤더를 가로채 401 이 반복된다.kinit -kt /etc/security/keytabs/hdfs.keytab hdfs/host.example.com@EXAMPLE.COM
export no_proxy="example.com,.example.com,localhost,127.0.0.1"
curl -v --negotiate -u : "<URL>" 2>&1 | egrep -i 'negotiate|www-authenticate|HTTP/'
KRB5_TRACE=/dev/stderr curl -s --negotiate -u : "<URL>" -o /dev/null
KRB5_TRACE 에는 어떤 서비스 프린시펄(HTTP/host@REALM)을 요청했는지가 그대로 찍힌다. 기대한 이름과 다르면 접속 URL 의 호스트 표기를 고친다.