Snowflake를 사용하여 경보 시스템 구축

» 블로그 » Snowflake를 사용하여 경보 시스템 구축

여기 있는 동안 Silverfort, 저는 Snowflake 데이터베이스에서 Slack 채널로 직접 메시지를 보내는 알림 시스템을 구축하는 임무를 받았습니다. 쉽게, 나는 속으로 생각했다. 그러나 이 프로젝트는 빠르게 확장되었고 이제 위협을 모니터링하고 완화하기 위해 매일 사용하는 중요한 구성 요소로 발전했습니다.

이 게시물에서는 Redshift에서 Snowflake로 전환한 직후 시작된 제 여정, 이 시스템 구축에 직면한 문제, 그리고 이를 극복할 수 있었던 방법을 여러분과 공유하고자 합니다. 

경보 시스템의 목표 – 위협 헌팅 팀이 고객을 위해 더 나은 가치를 창출하도록 지원

Silverfort 인증 트래픽과 환경의 정보를 분석하여 위반 사항을 감지하고 고객에게 경고합니다. 모든 탐지는 침해 지표(Indicator of Compromise, IOC)로 표시되어 단순한 구성 오류부터 잠재적인 악의적 공격에 이르기까지 다양한 사항에 대해 경고할 수 있습니다.

이 모든 정보는 제품에서 쉽게 사용할 수 있지만 고객은 각 IOC의 의미를 항상 이해하지 못할 수 있습니다. 또한 새로운 취약점과 공격 방법이 지속적으로 발견되고 있으며 제품에 완전히 통합되는 데 시간이 걸릴 수 있습니다.  

이러한 이유로 우리는 보안 이벤트에 대한 빠르고 효과적인 조사를 가능하게 하는 새로운 IOC 구현을 쉽게 추가하는 데 도움이 되는 경고 시스템을 만들고 싶었습니다.

첫 번째 반복과 제기된 문제

눈송이 및 눈알림

연구 및 분석 작업을 위한 데이터베이스로 Snowflake를 사용하기로 전환한 후 주목할 만한 보안 이벤트에 대한 알림을 Slack 채널로 보내는 데 Snowflake를 사용하는 것은 쉬운 일처럼 보였습니다.

Snowflake에는 이미 오픈 소스 구성 요소인 눈 경보, 정확한 목적을 위해 Snowflake 팀에서 개발했습니다. 보다 간소화된 솔루션을 타사 서비스로 사용할 수 있지만 문제의 데이터는 민감하기 때문에 필요한 경우가 아니면 외부 소스에 노출하고 싶지 않았습니다. 따라서 내부 머신에서 실행되는 Docker에서 이 SnowAlert 구성 요소를 실행하는 것이 좋은 솔루션이었습니다.

(SnowAlert 구성 요소에 대해 자세히 알아보려면 여기에서 유용한 자습서를 찾을 수 있습니다. ASlack에 알림.)

SnowAlert를 사용하여 Snowflake에서 알림을 보내려면 다음 위치에 배치해야 합니다. 눈송이 보기. 뷰는 테이블 또는 다른 뷰에 대한 저장된 하위 쿼리로, 일반 테이블에서 읽는 것처럼 이름이 지정되고 SQL 쿼리의 FROM 절에서 호출할 수 있습니다. 다른 보기 위에 보기를 사용할 수 있습니다. 이는 경보 시스템의 현재 반복을 빌드하는 데 많이 사용한 기능입니다.
SnowAlert 모듈이 원하는 알림을 보낼 위치를 알기 위해서는 전송된 메시지의 템플릿, 채널 유형(예: Slack, 이메일) 및 대상(예: 이메일 주소)을 지정하는 핸들러로 보기를 정의해야 합니다. , Slack 채널, Slack 다이렉트 메시지).  

뷰에 두 개의 핸들러를 정의하는 예,
 하나는 Slack 채널에, 다른 하나는 특정 이메일 주소에 할당합니다.

첫 구현 

이 경고 시스템을 구축하는 임무를 처음 받았을 때 우리는 XNUMX개의 서로 다른 IOC를 염두에 두었습니다. 이 모든 항목은 동일한 Snowflake 테이블에서 검색할 수 있으며 검색을 위한 간단한 논리가 있습니다. 요청된 날짜에 대해 테이블을 한 번 스캔하는 하나의 쿼리를 사용하여 모든 경고를 검색하기로 결정했습니다.

이 작업은 알림을 검색하기 위한 테이블 보기와 해당 보기를 SnowAlert 구성 요소에 필요한 형식으로 변환하기 위한 다른 버전의 보기를 생성하여 수행되었습니다. 이것은 잠시 동안 훌륭하게 작동했습니다… 

직면한 문제와 변화가 필요한 것 

일단 활성화되면 경고 시스템은 고객 환경에서 공격과 주목할만한 이벤트를 감지하여 계속해서 자체적으로 입증되었습니다. 이러한 성공을 바탕으로 다양한 수준의 복잡성을 가진 더 많은 IOC 탐지가 이 시스템에 추가되었습니다.

특정 조건이 충족될 때만 일부 경고가 트리거되기를 원했습니다. 그러나 일부는 다른 테이블 및 소스의 데이터와 결합해야 하므로 조인 및 집계 작업이 필요했습니다.

이것은 빠르게 괴물이 되었고 이 모든 것을 단일 보기(기본적으로 하나의 SQL 쿼리)에서 수행하는 것이 문제가 되기 시작했습니다.

다음은 우리가 직면한 몇 가지 문제입니다.

  • 경고가 추가됨에 따라 모든 행에 필요한 작업을 한 번에 수행하는 데 부담이 되고 느려졌습니다. 그리고 작업을 완료하는 데 필요한 시간이 급증하기 시작했습니다. 
  • 이 거대한 SQL 코드 블록을 디버깅하는 것은 악몽이었고 변경 및 업데이트가 어려워지고 오류가 발생하기 쉽습니다. 

더 많은 IOC에 대한 요청이 들어오면서 아키텍처의 대대적인 변경이 필요하다는 것이 분명해졌습니다.

 현재 아키텍처:   

따라서 순차적으로 병렬로 실행되는 일련의 다중 보기를 사용하는 현재 솔루션에 도달했습니다. 이 아키텍처의 기본 개념은 먼저 아키텍처를 두 부분으로 나누는 것입니다.

  1. ETL 및 경고 수집 부분(왼쪽에 표시됨):
    • 파이프라인을 사용하여 데이터 소스에서 알림 검색
      • 파이프라인은 유사한 특성(예: 공유 데이터 소스 및 데이터 작업)의 쿼리로 구성되어야 합니다.
    • 각 파이프라인의 끝에서 데이터가 "표준 형식"이고 동일한 구조를 포함하는지 확인합니다.
    • 모든 파이프라인의 데이터 통합 ​​및 메모리 테이블에 저장
  2. 경고 필터링 및 채널에 경고 할당:
    • 관련 경보 데이터를 검색하고 필요에 따라 필터를 수행합니다(예: 시간을 기준으로 오래된 경보 필터링).
    • 메시지당 알림 집계
    • 필요한 채널에 핸들러를 사용하여 집계 결과를 관련 뷰로 전송

주의 사항: 위의 다이어그램은 단일 채널에 대한 단일 흐름만 보여주지만 실제로는 여러 채널에 대한 이러한 흐름을 많이 생성할 수 있습니다.

중간에 테이블이 있는 프로세스를 두 부분으로 나누면 디버그 및 추적이 훨씬 쉬워집니다. 또한 서로 다른 시간이나 빈도로 두 부분을 실행할 수 있습니다.

전반적으로 아키텍처는 경고 시스템이 어떻게 사용되고 있는지와 필요한 미래 대비를 관찰한 후 이전 반복 중에 경험한 모든 문제점의 결과입니다. 데이터 소스 및 알림 메모리 테이블(Snowflake 테이블)을 제외하고 아키텍처의 다른 모든 개체는 Snowflake 보기입니다.

이것이 수많은 문제를 해결하는 이유

이렇게 복잡한 아키텍처가 도움이 되는 이유는 무엇입니까? 몇 가지 주요 개념을 유지하기 때문입니다.

캡슐화

일련의 보기를 생성한다는 것은 모든 섹션을 독립적으로 실행하고 디버그할 수 있음을 의미합니다. 이를 통해 디버깅 시간을 절약할 수 있을 뿐만 아니라 더 깨끗하고 쉽게 업데이트할 수 있습니다. 이는 객체 지향 프로그래밍 언어에서 잘 작동하는 개념이며 여기에도 적용됩니다.

표준화

논리를 원하는 만큼 복잡하게 만들 수 있지만 모든 파이프라인 끝에 있는 데이터는 정확히 동일한 구조를 포함해야 합니다. 이를 통해 서로 다른 수준의 복잡한 논리를 사용하는 다양한 파이프라인을 하나의 일관된 파이프라인으로 결합할 수 있습니다.

병렬화

순차 보기와 병렬 보기(모두 하위 쿼리)의 조합을 사용하여 병렬화의 이점을 얻습니다. 서로 다른 파이프라인은 합집합이 수행될 때까지 완전히 독립적이므로 Snowflake는 각 파이프라인을 일련의 병렬 하위 쿼리로 실행할 수 있습니다. 각 파이프라인을 동일한 유형의 작업(예: 사용자 집계)이 필요한 경고로 구성함으로써 데이터에 대한 동일한 전달에서 여러 감지를 수행할 수 있습니다(이전 구현과 동일하지만 더 집중됨). 이는 성능 향상에 도움이 됩니다.

자동화

의 조합을 사용하여 예약 된 일들, UDF절차 Snowflake 데이터베이스에 통합되어 전체 프로세스를 자동화하여 변경 사항을 감지하고 적응할 수 있습니다. 파이프라인의 프로세스에 추가된 새 경고는 상위 수준에서 감지되므로 파이프라인 수준 이상으로 업데이트가 필요하지 않습니다.

프로세스 독립성

경고를 추가할 때 해당 경고의 파이프라인 외부에서 보기를 변경할 필요가 없습니다. 또한 더 많은 채널을 추가하거나 경고에 대한 필터 또는 집계를 변경해도 파이프라인을 변경할 필요가 없습니다.

이것이 Snowflake에서 구현되는 방식

캡슐화 및 병렬화

이는 순차 뷰의 여러 파이프라인을 사용하여 구현되며, 특히 각 파이프라인을 파이프라인의 논리적 단계를 나타내는 각 뷰와 함께 여러 뷰로 세분화합니다. 이러한 모든 파이프라인의 합집합은 또 다른 보기이며 해당 보기에서 호출하면 Snowflake가 모든 기본 파이프라인을 하위 쿼리로 병렬로 실행합니다.

프로세스 독립성

이것은 먼저 경고 메모리 테이블을 보기가 아닌 실제 테이블로 만들어 달성됩니다. 통계를 보는 데 사용할 수 있는 시간 경과에 따른 알림을 수집합니다. 가장 중요한 것은 그것을 테이블로 만든다는 것은 그것이 저장된다는 것을 의미하며, 이는 우리가 그 위에 여러 프로세스를 구축할 수 있음을 의미합니다(예: 다양한 수준의 집계 및/또는 필터링이 필요한 여러 채널의 경우).

표준화

각 파이프라인은 표준 구조를 갖는 데이터로 끝나야 합니다. 이렇게 하면 각 행에 고객 및 날짜당 단일 경고 유형이 있으므로 스키마를 변경하고 추가 열을 추가할 필요가 없으므로 더 많은 경고 유형을 간단하게 추가할 수 있습니다. 새로운 경고에 대한 정보를 포함하지만 이전 경고와 동일한 스키마를 사용하는 행을 더 추가하기만 하면 됩니다.


또한 모든 파이프라인이 이 표준을 준수해야 하므로 간단히 UNION ALL 그들 사이에. 각 파이프라인에서 이 양식을 얻으려면 먼저 데이터를 집계하여 각 경고에 대한 열을 가져옵니다. 그런 다음 우리는 UNPIVOT 뷰를 표준 형식으로 가져옵니다.

자동화

스키마를 업데이트해야 하거나 새 경고가 위쪽으로 전파되는지 걱정할 필요가 없기 때문에 프로세스를 자동화하여 새 경고를 감지합니다. 이는 경고를 열에서 행으로 변환하는 피벗 취소 프로세스를 통해 수행됩니다.

동적 언피벗(동적 열 집합에 대한)은 SQL에서 기본적으로 지원되지 않기 때문에 이 자동화를 적용하기 위해 Snowflake의 프로시저 및 예약된 작업을 사용했습니다. 이 프로시저는 경고 열 목록에서 보기의 피벗을 해제하고 피벗 해제 보기를 생성합니다. 예약된 작업은 새 경고가 추가되었는지 감지하기 위해 언피벗이 필요한 모든 보기에 대한 프로시저 생성을 호출합니다. 따라서 추가된 새 경고는 자동으로 행으로 변환됩니다.

절차 역동적 인 보기에서 새 보기로 피벗 해제 

모든 것이 수행되는 방식


지금까지 성능(동일한 컴퓨팅 성능을 사용하여 10배 이상 빨라진 것으로 보임)과 운영 비용 절감뿐만 아니라 시스템 사용이 더 편안해졌기 때문에 엄청난 개선이 있었다는 것을 보고하게 되어 기쁩니다.

이 새로운 반복이 출시된 이후 훨씬 더 복잡한 논리로 새로운 경고를 추가했습니다. 지금까지 이것은 더 빠른 디버깅 및 테스트와 변경 사항 구현 측면에서 훨씬 더 나은 경험이었습니다. 새 경고를 추가하는 것은 이제 간단한 SQL 쿼리를 작성하고 주요 위치에서 파이프라인 업데이트를 확인하는 문제입니다. 테스트를 포함한 모든 작업을 XNUMX분 이내에 완료할 수 있습니다. 나머지는 더 이상 걱정할 필요가 없습니다.



인증 공격 막기