보안 모델

보안 모델 (Security model)

프로메테우스를 운영하면서 가장 먼저 알아야 할 것 중 하나가 바로 보안이에요. 이 문서는 프로메테우스가 전제하고 있는 보안 가정(assumptions)과, 특정 구성이 만들어 낼 수 있는 공격 벡터(attack vectors)를 설명해 드려요. 모니터링 시스템은 결국 감시 대상 시스템의 정보를 모으고 제공하기 때문에, 노출 범위를 잘 파악하고 있어야 안전하게 운영할 수 있어요.

이 문서의 핵심 메시지 한 가지는 분명해요. 프로메테우스 컴포넌트가 제공하는 HTTP 엔드포인트는 공개 인터넷 같은 곳에 노출하면 안 된다는 거예요. 서버에서는 어떤 설정이 위험한지, 무엇이 기본값으로 꺼져 있는지, 보고 책임이 어디 있는지 차근차근 알아 볼게요.

출처: 문서

본문

주의: 아래 기술적 세부 내용에 들어가기 전에 강조하고 싶은 점은, 프로메테우스는 모니터링 시스템으로서 감시 대상 시스템에 대한 정보를 수집하고 제공한다는 거예요. 따라서 프로메테우스 컴포넌트가 제공하는 HTTP 엔드포인트는 인터넷 같은 공개적으로 접근 가능한 네트워크에 노출해서는 안 돼요(무엇을 하고 있는지 잘 알면서 적절한 조치를 취한 경우가 아니라면요). 이는 계측된 바이너리의 /metrics 엔드포인트, 서버 컴포넌트의 다양한 API 엔드포인트, 그리고 Go로 구현된 서버 컴포넌트의 /pprof 엔드포인트를 포함하지만 여기에 국한되지는 않아요. 게다가 이런 엔드포인트에 대한 요청으로 서버를 쉽게 과부하시켜 최종적으로 DoS까지 일으킬 수 있어요.

프로메테우스는 많은 컴포넌트와 다른 시스템과의 많은 통합을 가진 정교한 시스템이에요. 신뢰하는 환경과 신뢰하지 않는 환경에 다양하게 배포될 수 있어요.

이 페이지는 프로메테우스의 일반적인 보안 가정과, 일부 구성이 가능하게 하는 공격 벡터를 설명해요.

어떤 복잡한 시스템이든 마찬가지로, 버그가 발견될 가능성은 거의 확실하고 그중 일부는 보안과 관련될 거예요.

이미 공개적으로 알려진(예: 공개 CVE를 통해) 보안 버그 중, 의존성 버전 올리기보다 더 많은 수정이 필요한 경우에는, 이미 등록된 이슈가 없다면 관련 모든 세부 정보를 포함해 버그 리포트를 열어 주세요.

아직 공개적으로 알려지지 않은 보안 버그를 발견했다면, 관련 저장소의 MAINTAINERS에 나열된 유지보수자에게 비공개로 보고하고 [email protected]를 참조(CC)해 주세요. 우리는 가능한 한 빨리 문제를 수정하고 여러분과 릴리스 날짜를 조율할 거예요. 여러분의 노력에 대한 공개적인 인정을 원하는지, 이름을 언급하고 싶은지 선택할 수 있어요.

대부분의 의존성 버전 업데이트는 자동으로 처리돼요. 하지만 보안 버그 수정이 의존성 버전 업데이트만으로 충분한데도 자동화가 놓쳤다면, 업데이트를 직접 제출해도 됩니다.

자동 보안 스캐너

보안 스캐너 사용자에게 특별히 드릴 말씀: 생성되는 보고서에 주의해 주세요. 대부분의 스캐너는 일반적(generic)이고 많은 오탐(false positive)을 만들어 냅니다. 점점 더 많은 보고서가 우리에게 전송되고 있고, 그 모든 것을 검토하고 여러분이 기대하는 수준의 답변을 하는 데 상당한 작업이 필요해요. 이 문제는 특히 Go와 NPM 의존성 스캐너에서 심각해요.

우리와 우리 시간에 대한 예의로, 원본 보고서를 그대로 제출하지 말아 주세요. 대신 어떤 특정 결과가 우리에게 적용되는지, 그리고 그 이유를 설명하는 분석과 함께 제출해 주세요.

또한 오픈소스 프로젝트로서 우리는 일반적으로 상용 스캐닝 도구에 접근할 수 없고, 그 출력이 종종 오해를 부르거나 그냥 틀린 경우가 많다는 점을 알아 두세요. Go 코드의 경우, 여러분의 보고가 (전체 분석이 불가능한 바이너리가 아니라) 영향받는 것으로 믿는 버전의 소스 코드에서 실행한 오픈소스 govulncheck 도구로 재현되지 않는다면, 여러분의 발견(그 코드가 실제로 Prometheus 코드베이스 안에서 도달 가능한지 포함)을 삼중으로 확인해 달라고 요청해요.

프로메테우스는 회사가 아니라 자원봉사자에 의해 유지보수돼요. 따라서 보안 이슈 수정은 최선 노력(best-effort)으로 이뤄져요. 우리는 Prometheus, Alertmanager, Node Exporter, Blackbox Exporter, Pushgateway에 대해 7일 안에 보안 수정을 릴리스하기 위해 노력해요.

Prometheus

신뢰하지 않는 사용자가 Prometheus HTTP 엔드포인트와 로그에 접근할 수 있다고 가정해요. 그들은 데이터베이스에 포함된 모든 타임시리즈 정보와, 다양한 운영/디버깅 정보에 접근할 수 있어요.

또한 신뢰할 수 있는 사용자만이 Prometheus 및 다른 컴포넌트의 커맨드라인, 구성 파일, 규칙 파일, 기타 런타임 환경 측면을 변경할 수 있다고 가정해요.

Prometheus가 어떤 타깃을 스크랩할지, 얼마나 자주, 어떤 다른 설정으로 할지는 전적으로 구성 파일을 통해 결정돼요. 관리자는 서비스 디스커버리 시스템의 정보를 사용하기로 결정할 수 있는데, 이는 relabeling과 결합하면 그 서비스 디스커버리 시스템에서 데이터를 수정할 수 있는 사람 누구에게나 이 제어권 일부를 부여할 수 있어요.

스크랩된 타깃은 신뢰하지 않는 사용자에 의해 실행될 수 있어요. 기본적으로 타깃이 다른 타깃을 사칭하는 데이터를 노출하는 것은 가능해서는 안 돼요. honor_labels 옵션은 이 보호를 제거하며, 특정 relabeling 구성도 마찬가지로 제거할 수 있어요.

Prometheus 2.0부터 --web.enable-admin-api 플래그가 타임시리즈 삭제 같은 기능을 포함하는 관리 HTTP API에 대한 접근을 제어해요. 기본적으로 비활성화돼 있어요. 활성화하면 관리 및 변경(mutating) 기능이 /api/*/admin/ 경로 아래에서 접근 가능해져요. --web.enable-lifecycle 플래그는 Prometheus의 HTTP 리로드와 셧다운을 제어해요. 이것도 기본적으로 비활성화돼 있어요. 활성화하면 /-/reload/-/quit 경로에서 접근할 수 있어요.

Prometheus 1.x에서는 /-/reload/api/v1/seriesDELETE를 사용하는 것이 HTTP API에 접근할 수 있는 사람 누구에게나 가능해요. /-/quit 엔드포인트는 기본적으로 비활성화돼 있지만 -web.enable-remote-shutdown 플래그로 활성화할 수 있어요.

원격 읽기(remote read) 기능은 HTTP 접근이 있는 사람 누구나 원격 읽기 엔드포인트에 쿼리를 보낼 수 있게 해요. 예를 들어 PromQL 쿼리가 관계형 데이터베이스에 직접 실행된다면, (예: Grafana를 통해) Prometheus에 쿼리를 보낼 수 있는 사람은 누구나 그 데이터베이스에 임의의 SQL을 실행할 수 있어요.

Alertmanager

Alertmanager HTTP 엔드포인트에 접근할 수 있는 모든 사용자는 그 데이터에 접근할 수 있어요. 알림을 만들고 해결할 수 있고, 사일런스(silence)를 생성·수정·삭제할 수 있어요.

어떤 형태의 인증도 구성하지 않은 운영자는 주의해야 해요: Alertmanager는 /api/v2Access-Control-Allow-Origin: *로 서빙해요. 이는 서비스에 도달할 수 있는 브라우저가 방문한 모든 웹사이트에 API 접근을 부여해요.

알림 통지(notification)가 어디로 전송되는지는 구성 파일에 의해 결정돼요. 특정 템플릿 구성에서는 알림이 알림 정의 목적지로 전달될 수 있어요. 예를 들어 알림이 목적지 이메일 주소로 알림 라벨을 사용한다면, Alertmanager에 알림을 보낼 수 있는 사람은 누구나 어떤 이메일 주소로도 알림을 보낼 수 있어요. 알림 정의 목적지가 템플릿 가능한 시크릿 필드라면, Prometheus나 Alertmanager에 접근할 수 있는 사람은 누구나 그 시크릿을 볼 수 있어요.

템플릿 가능한 모든 시크릿 필드는 위의 사용 사례에서 알림 라우팅을 위해 의도된 것이에요. 템플릿 파일 기능을 사용해 구성 파일에서 시크릿을 분리하는 방법으로 의도된 것이 아니에요. 템플릿 파일에 저장된 시크릿은 Alertmanager 구성 파일에서 수신기(receivers)를 구성할 수 있는 사람이라면 누구나 유출(exfiltrate)시킬 수 있어요. 예를 들어 대규모 구성에서는 각 팀이 완전히 통제하는 alertmanager 구성 파일 조각을 가질 수 있고, 그 조각들이 최종 전체 구성 파일로 결합돼요.

Pushgateway

Pushgateway HTTP 엔드포인트에 접근할 수 있는 모든 사용자는 그 안에 포함된 메트릭을 생성·수정·삭제할 수 있어요. Pushgateway는 보통 honor_labels를 활성화한 상태로 스크랩되므로, Pushgateway에 접근할 수 있는 사람은 누구나 Prometheus에 어떤 타임시리즈든 만들 수 있어요.

--web.enable-admin-api 플래그가 기존의 모든 메트릭 그룹을 지우는(wiping) 기능을 포함하는 관리 HTTP API에 대한 접근을 제어해요. 기본적으로 비활성화돼 있어요. 활성화하면 관리 기능이 /api/*/admin/ 경로 아래에서 접근 가능해져요.

익스포터 (Exporters)

익스포터는 일반적으로 사전 설정된 명령/요청 세트로 하나의 구성된 인스턴스와만 통신하며, HTTP 엔드포인트로 확장할 수 없어요.

SNMP와 Blackbox 익스포터 같은 일부 익스포터는 URL 파라미터에서 타깃을 가져와요. 따라서 이들 익스포터에 HTTP 접근이 있는 사람은 누구나 임의의 엔드포인트에 요청을 보내게 할 수 있어요. 또한 클라이언트 측 인증을 지원하므로, HTTP Basic Auth 비밀번호나 SNMP 커뮤니티 문자열 같은 시크릿의 누출로 이어질 수 있어요. TLS 같은 챌린지-응답 인증 메커니즘은 이 영향을 받지 않아요.

클라이언트 라이브러리 (Client Libraries)

클라이언트 라이브러리는 사용자 애플리케이션에 포함되도록 의도돼 있어요.

클라이언트 라이브러리가 제공하는 HTTP 핸들러를 사용한다면, 그 핸들러에 도달하는 악의적인 요청이 추가 로드와 실패한 스크랩에서 비롯된 문제를 넘어서는 문제를 일으키지 못해야 해요.

인증, 권한 부여, 암호화 (Authentication, Authorization, and Encryption)

Prometheus와 대부분의 익스포터는 TLS를 지원해요. TLS 클라이언트 인증서를 통한 클라이언트 인증을 포함해요. Prometheus 구성에 대한 자세한 내용은 여기를 보세요.

Go 프로젝트는 Go crypto/tls 라이브러리 기반의 동일한 TLS 라이브러리를 공유해요. 최소 버전으로 TLS 1.2를 기본값으로 사용해요. 이에 대한 정책은 Qualys SSL Labs 권장 사항을 기반으로 하며, 업스트림 Go 기본값에 최대한 가깝게 유지하면서 기본 구성과 올바르게 제공된 인증서로 등급 'A'를 달성하기 위해 노력해요. 그 등급을 달성하는 것은 완벽한 보안과 사용성 사이의 균형을 제공해요.

TLS는 미래에 Java 익스포터에 추가될 거예요.

다른 암호 스위트나 더 오래된 TLS 버전 같은 특별한 TLS 요구가 있다면, crypto/tls 라이브러리에서 안전하지 않은 것으로 표시되지 않는 한 최소 TLS 버전과 암호를 조정할 수 있어요. 그런데도 맞지 않다면, 현재 TLS 설정으로 더 특별한 요구가 있는 서버와 리버스 프록시 사이에 보안 터널을 구축할 수 있어요.

HTTP Basic Authentication도 지원돼요. Basic Authentication은 TLS 없이 사용할 수 있지만, 그러면 사용자 이름과 비밀번호가 네트워크에 평문으로 노출돼요.

서버 측에서 basic authentication 비밀번호는 bcrypt 알고리즘으로 해시로 저장돼요. 여러분의 보안 기준에 맞는 라운드 수를 선택하는 것은 여러분의 책임이에요. 라운드가 많을수록 브루트포스가 더 복잡해지지만 CPU 전력과 요청 인증 시간이 더 들어요.

다양한 Prometheus 컴포넌트가 클라이언트 측 인증과 암호화를 지원해요. TLS 클라이언트 지원이 제공된다면, 보통 insecure_skip_verify라고 하는 SSL 검증을 건너뛰는 옵션도 있는 경우가 많아요.

API 보안 (API Security)

관리 및 변경(mutating) 엔드포인트는 cURL 같은 간단한 도구를 통해 접근되도록 의도됐기 때문에, 내장된 CSRF 보호는 없어요. 그런 보호는 그런 사용 사례를 깨뜨릴 거예요. 따라서 리버스 프록시를 사용할 때 CSRF를 막기 위해 그런 경로를 차단하고 싶을 수 있어요.

변경이 아닌(non-mutating) 엔드포인트에서는 XSS를 막기 위해 리버스 프록시에서 Access-Control-Allow-Origin 같은 CORS 헤더를 설정하고 싶을 수 있어요.

신뢰하지 않는 사용자(예: 콘솔 템플릿에 대한 URL 파라미터, 또는 직접 만든 것)의 입력을 포함하는 PromQL 쿼리를 구성하면서, 그들이 임의의 PromQL 쿼리를 실행할 수 없도록 의도된 경우라면, 인젝션 공격을 막기 위해 신뢰하지 않는 입력이 적절히 이스케이프되는지 확인하세요. 예를 들어 up{job=""}는, ``이 "} or some_metric{zzz="라면 up{job=""} or some_metric{zzz=""}가 될 거예요.

Grafana를 사용하는 분들은 대시보드 권한은 데이터 소스 권한이 아니라는 점을 기억하세요. 프록시 모드에서 임의 쿼리를 실행하는 사용자의 능력을 제한하지 마세요.

시크릿 (Secrets)

비시크릿(non-secret) 정보나 필드는 HTTP API 및/또는 로그를 통해 이용 가능할 수 있어요.

Prometheus에서 서비스 디스커버리에서 검색된 메타데이터는 시크릿으로 간주되지 않아요. Prometheus 시스템 전체에서 메트릭은 시크릿으로 간주되지 않아요.

구성 파일에서 시크릿을 포함하는 필드(문서에서 명시적으로 그렇게 표시된)는 로그나 HTTP API를 통해 노출되지 않아요. 컴포넌트가 구성 파일을 HTTP 엔드포인트를 통해 노출하는 것이 흔하기 때문에, 시크릿은 다른 구성 필드에 두지 않아야 해요. 디스크의 파일을 원치 않는 읽기와 쓰기로부터 보호하는 것은 사용자의 책임이에요.

의존성이 사용하는 다른 소스의 시크릿(예: EC2 서비스 디스커버리가 사용하는 AWS_SECRET_KEY 환경 변수)은 우리 통제 밖의 코드나, 저장 위치가 노출되는 기능 때문에 드러날 수 있어요.

서비스 거부 (Denial of Service)

과도한 로드나 비싼 쿼리에 대한 몇 가지 완화 조치가 있어요. 하지만 너무 많거나 너무 비싼 쿼리/메트릭이 제공되면 컴포넌트는 넘어질 거예요. 악의적인 행동보다는 신뢰하는 사용자가 실수로 컴포넌트를 다운시킬 가능성이 더 높아요.

우리는 순수한 서비스 거부 이슈를 비공개 공개를 요구하는 보안 취약점으로 간주하지 않아요. 요청을 보내서 Prometheus 컴포넌트가 크래시되거나 사용 불가능해지는 것을 발견했다면, 그건 위의 보안 모델을 고려했을 때 일반적으로 예상되는 동작이에요. 이를 비공개 공개 과정을 통해 보안 버그로 보고하지 말아 주세요.

그렇긴 해도, 수정이 여전히 가치 있는 경우가 있고 공개 이슈나 풀 리퀘스트는 환영해요. 좋은 예는 공격자가 통제하는 길이 필드가 검증 없이 신뢰되어 메모리 할당에 사용되는 로직 버그예요 — 이는 비공개 보안 보고 수준에는 못 미치더라도 리소스 안전성에 의미 있는 개선이에요. 반면, 코드베이스 일부에서 임의의 상태 검사(sanity limits)가 없는 것은 일반적으로 그 자체만으로 보고할 가치가 없어요.

악의적인 공격 시나리오를 넘어서, CPU, RAM, 디스크 공간, IOPS, 파일 디스크립터, 대역폭을 포함한 충분한 리소스를 컴포넌트에 제공하는 것은 사용자의 책임이에요.

모든 컴포넌트를 실패에 대해 모니터링하고, 실패 시 자동으로 재시작하도록 하는 것을 권장해요.

라이브러리 (Libraries)

이 문서는 스톡 소스 코드에서 빌드된 바닐라 바이너리를 고려해요. 여기 제시된 정보는 Prometheus 소스 코드를 수정하거나, (공식 클라이언트 라이브러리 API를 넘어서는) Prometheus 내부를 여러분의 코드에서 사용한다면 적용되지 않아요.

빌드 과정 (Build Process)

Prometheus의 빌드 파이프라인은 Prometheus 개발팀의 많은 구성원과 그 공급자의 직원이 접근할 수 있는 서드파티 공급자에서 실행돼요. 바이너리의 정확한 출처(provenance)가 걱정된다면, 프로젝트가 제공하는 미리 빌드된 바이너리에 의존하기보다 직접 빌드하는 것을 권장해요.

Prometheus-Community

Prometheus-Community 조직 아래의 저장소는 서드파티 유지보수자가 지원해요.

Prometheus-Community 조직에서 보안 버그를 발견했다면, 관련 저장소의 MAINTAINERS에 나열된 유지보수자에게 비공개로 보고하고 [email protected]를 참조(CC)해 주세요.

그 조직 아래의 일부 저장소는 이 문서에 제시된 것과 다른 보안 모델을 가질 수 있어요. 그런 경우 그 저장소의 문서를 참조해 주세요.

외부 감사 (External audits)

2018년에 CNCFcure53의 외부 보안 감사를 후원했으며, 2018년 4월부터 2018년 6월까지 진행됐어요. 자세한 내용은 감사 최종 보고서를 읽어 보세요.

2020년에 CNCF가 Node Exporter에 대한 cure53의 두 번째 감사를 후원했어요.

2023년에 CNCF가 Chainguard의 Prometheus 소프트웨어 공급망 보안 평가를 후원했어요.

더 알아보기 (Learn more)