현재 투입된 프로젝트에서 Trino 쿼리엔진을 활용하고있습니다. Fast API를 이용하여 API로 Trino에 쿼리를 날리고 있지만,
특정 사용자의 경우 직접 데이터에 쿼리를 날리고 싶다는 클라이언트의 요구사항이 있었습니다.
Trino에서 간단하게 id/password로 보안요소를 적용해보려고 합니다.
실습환경은 Docker를 사용하였고, 실 운영 환경은 K8S로 운영되지만 이번예제는 간단하게 config 수정을 볼 것이기 때문에
config에 집중하면 좋을 것 같습니다.
참고링크 : https://trino.io/docs/current/security/password-file.html
Password file authentication — Trino 463 Documentation
Password file authentication Trino can be configured to enable frontend password authentication over HTTPS for clients, such as the CLI, or the JDBC and ODBC drivers. The username and password are validated against usernames and passwords stored in a file.
trino.io
Trino 공식문서를 확인하면, 간단하게 ID/Password를 적용하는 방법을 안내하고 있습니다.
Dockerfile
FROM trinodb/trino:462
ARG IS_COORDINATOR
ENV IS_COORDINATOR=${IS_COORDINATOR:-true}
COPY --chmod=777 ./docker-entrypoint.sh ./docker-entrypoint.sh
COPY ./coordinator/config.properties /home/trino/coordinator/config.properties
COPY ./worker/config.properties /home/trino/worker/config.properties
COPY ./auth/password-authenticator.properties /etc/trino/password-authenticator.properties
COPY ./auth/password.db /etc/trino/auth/password.db
ENTRYPOINT ["/bin/sh", "-c", "./docker-entrypoint.sh"]
docker image 한개를 활용하여, Coordinator, Worker를 배포하고 싶어서
IS_COORDINATOR 환경변수로 Coordinator, Worker를 구분하였습니다.
Coordinator config
coordinator=true
node-scheduler.include-coordinator=false
http-server.http.port=8080
catalog.management=${ENV:CATALOG_MANAGEMENT}
#authentication
#discovery.uri=http://localhost:8080
http-server.authentication.type=PASSWORD
internal-communication.shared-secret="4gcpR8hEL9rP1la+H30v4uH17R2WOEjWp9tKN3J0y6wAtRSIyw7+jxHmh/8JZWl8x9/0Y2r5jxMX4RjeJ3NkpISht+ycmleeJT+IQxQpa2JTC6JwWhQCcjNdLJqHHIhTndneGT2oCqv3cmpYWvJQukYivNowd+2A5vbRaY123f8Un87oSmKEVyZ/fwFaXktUwrYSvFDlhCYTZuukbqbDCnBueTASj8Aa+F8yV0MPSYhbtGtFMUjSo6oSbLHknO5SkPPv55X4irP5vIAEu5gr6hXO9LpPScMo/XndZAKnc5g5KJ+VKClC+m38DEqNiFfiEoS72Eo9ioP88Rc/6kxQAQ3gM/KINmAMIbz7XuhsnOzjiMCBMUK/S+zdgtBj1ioSdXeRvhz8v7FmMX/dGxLdJIBn1J8Llv0IHif9FeBIeLMMJVE17rTA0HzxEWz+AX/qyOXfMMjvyzr/wc3Qall09fKBbo5D71OEqVSPUPayEMlvm8VPzQA7riyBo5dHsKZsCwLyz3Qx5iP75Tfcxvi4You/eeHpa6zPTU3bJJU5P42Ygjt68Qa/xHbG6Ue21bMNtavLTXnKCpB8g6UPcZXmU2j6yS72y4ZrPKFGtFBK3EypB5SUl29g8+taxpBg3xc0kpb8Lh9fkVpyKFJgF1usJIVxZVq5xlG9GJGaiUkK8oQ="
internal-communication.https.required=true
discovery.uri=https://trino-coordinator:8443
http-server.https.enabled=true
http-server.https.port=8443
internal-communication.shared-secret
해당 config의 경우 클러스터의 내부통신을 위하여 사용하는 것으로 Coordinator, Worker 동일하게 설정해야합니다.
openssl rand 16(숫자) | base64
위 명령어로 랜덤한 값을 추출하여 적용하였습니다.
Worker config
coordinator=false
node-scheduler.include-coordinator=true
http-server.http.port=8080
catalog.management=${ENV:CATALOG_MANAGEMENT}
#authentication
http-server.authentication.type=PASSWORD
internal-communication.shared-secret="4gcpR8hEL9rP1la+H30v4uH17R2WOEjWp9tKN3J0y6wAtRSIyw7+jxHmh/8JZWl8x9/0Y2r5jxMX4RjeJ3NkpISht+ycmleeJT+IQxQpa2JTC6JwWhQCcjNdLJqHHIhTndneGT2oCqv3cmpYWvJQukYivNowd+2A5vbRaY123f8Un87oSmKEVyZ/fwFaXktUwrYSvFDlhCYTZuukbqbDCnBueTASj8Aa+F8yV0MPSYhbtGtFMUjSo6oSbLHknO5SkPPv55X4irP5vIAEu5gr6hXO9LpPScMo/XndZAKnc5g5KJ+VKClC+m38DEqNiFfiEoS72Eo9ioP88Rc/6kxQAQ3gM/KINmAMIbz7XuhsnOzjiMCBMUK/S+zdgtBj1ioSdXeRvhz8v7FmMX/dGxLdJIBn1J8Llv0IHif9FeBIeLMMJVE17rTA0HzxEWz+AX/qyOXfMMjvyzr/wc3Qall09fKBbo5D71OEqVSPUPayEMlvm8VPzQA7riyBo5dHsKZsCwLyz3Qx5iP75Tfcxvi4You/eeHpa6zPTU3bJJU5P42Ygjt68Qa/xHbG6Ue21bMNtavLTXnKCpB8g6UPcZXmU2j6yS72y4ZrPKFGtFBK3EypB5SUl29g8+taxpBg3xc0kpb8Lh9fkVpyKFJgF1usJIVxZVq5xlG9GJGaiUkK8oQ="
internal-communication.https.required=true
discovery.uri=https://trino-coordinator:8443
http-server.https.enabled=true
http-server.https.port=8443
AUTH
password-authenticator.properties
trino서버가 시작될때, 해당 properties의 내용을 읽어 정보를 확인합니다.
password-authenticator.name=file
file.password-file=/etc/trino/auth/password.db
간단하게 type은 file로 해당 경로의 password.db를 주기적으로 읽어옵니다.
testuser:$2y$10$fREsmttvIor/PfbaGn6Ptu5VJHhOAgI9SbJWpDGwWjhdV3Gaai..i
id: testuser
pw: testuser
로 지정하였고 명령어는 아래와 같습니다.
htpasswd -B -b -C password.db {user} {password}
htpasswd를 통하여 bcrypt 패스워드를 생성하고 cost값은 8이상의 값을 사용해야 하여 10을 지정하였습니다.
실행 Command 및 연결
docker network create trino
docker run -e IS_COORDINATOR=true -d --name trino-coordinator -p 8443:8443 -p 8080:8080 --network trino trino-custom:latest
docker run -e IS_COORDINATOR=false -d --name trino-worker --network trino trino-custom:latest
JDBC(DBeaver)
jdbc를 활용하여 쿼리를 할때 아래의 key, value를 설정하였습니다.
CLI
trino --user={USER} --password https://trino-coordinator:8443?SSLVerification=NONE
#password 입력
외부에서는 8443(https) 포트를 포트포워딩하여 접근할 수 있습니다.
간단하게 https 및 id/password를 적용했지만, 실 운영 환경에는 부합하지 않을 수 있습니다.
keycloak, kerberos 같은 보안시스템을 고려해야 할 것입니다.
기록
1. discovery.uri 세팅
k8s에서 배포하여, 외부 내부 모두 https로 설정하였고, 내부 클러스터 통신시 worker에서 discovery.uri를 coordinator의 클러스터 도메인을 적용하였지만 연결하지 못하는 이슈가 발생하였음.
외부로 노출할 때는 https, 내부 통신은 http로 통신하여 해결하였음.
tls(ssl), jwt, 인증서 등 여러 보안인증요소를 고려해야함.
2. password.db 읽기
k8s에서 secret으로 password.db를 만들어 적용하니, 유저가 추가되거나 수정사항이 발생했을 때 이슈가 발생함.
pod으로 배포되었기 때문에 이후에 변경된 secret, config를 다시 읽으려면 restart가 필요해짐.
rollout restart로 trino 클러스터를 재시작하여 적용하면 간단하게 해결할 수 있지만, 매번 클러스터를 재시작할 수는 없기 때문에
keycloak같은 시스템을 쓰는구나하고 느낄 수 있었음.
k8s 활용(MSA), 클러스터의 도입으로 네트워크 통신은 많아지며, 자연스럽게 네트워크 및 보안에 대하여 연구가 필요해짐
'데이터 엔지니어링' 카테고리의 다른 글
[KAFKA] 기록#1 [listeners vs advertised.listeners] feat Nifi (0) | 2024.11.28 |
---|---|
[Airflow] Webserver 속도 개선 (0) | 2024.11.04 |
[PyFlink] 기록 # 2 Iceberg 도입시 Error (1) | 2024.09.21 |
[PyFlink] 기록#1 Dictionary in List 처리 (1) | 2024.08.31 |
[Flink] Flink Architecture (0) | 2024.08.24 |