다음을 통해 공유


복원력을 위한 애플리케이션 로그인 상태 모니터링

인프라 복원력을 높이려면 중요한 애플리케이션에 대한 애플리케이션 로그인 상태 모니터링을 설정합니다. 영향을 주는 인시던트가 발생할 때 경고를 받을 수 있습니다. 이 문서에서는 사용자의 로그인 중단을 모니터링하기 위해 앱 로그인 상태 통합 문서를 설정하는 과정을 안내합니다.

앱 로그인 상태 통합 문서를 기반으로 경고를 구성할 수 있습니다. 이 통합 문서를 통해 관리자가 테넌트에서 애플리케이션의 인증 요청을 모니터링할 수 있습니다. 다음과 같은 주요 기능을 제공합니다.

  • 거의 실시간 데이터로 모든 또는 개별 앱을 모니터링하도록 통합 문서를 구성합니다.
  • 조사하고 대응할 수 있도록 인증 패턴 변경에 대한 경고를 구성합니다.
  • 일정 기간 동안의 추세를 비교합니다. 주별 통합 문서의 기본 설정입니다.

참고 항목

보고서에 Azure Monitor 통합 문서를 사용하는 방법에서 사용 가능한 모든 통합 문서와 이를 사용하기 위한 필수 조건을 확인합니다.

영향을 주는 이벤트 중에는 다음 두 가지가 발생할 수 있습니다.

  • 사용자가 로그인할 수 없으면 애플리케이션에 대한 로그인 수가 갑자기 줄어들 수 있습니다.
  • 로그인 실패 횟수가 증가할 수 있습니다.

필수 조건

앱 로그인 상태 통합 문서 구성

Azure Portal에서 통합 문서에 액세스하려면 Microsoft Entra ID를 선택하고 통합 문서를 선택합니다.

통합 문서는 사용 방법, 조건부 액세스문제 해결 아래에 표시됩니다. 앱 로그인 상태 통합 문서는 상태 섹션에 표시됩니다. 통합 문서를 사용한 후에는 최근에 수정된 통합 문서 섹션에 표시될 수 있습니다.

앱 로그인 상태 통합 문서를 사용하여 로그인에 어떤 일이 일어나고 있는지 시각화할 수 있습니다. 다음 스크린샷에 표시된 것처럼 통합 문서에는 두 개의 그래프가 표시됩니다.

로그인 상태 그래프를 보여주는 스크린샷입니다.

앞의 스크린샷에는 두 개의 그래프가 있습니다.

  • 시간당 사용량(성공한 사용자 수). 현재 성공적인 사용자 수를 일반적인 사용 기간과 비교하면 조사가 필요할 수 있는 사용량 감소를 파악하는 데 도움이 됩니다. 성공한 사용률 저하는 실패 사용률로 검색할 수 없는 성능 및 사용률 문제를 검색하는 데 도움이 될 수 있습니다. 예를 들어, 사용자가 로그인을 시도하기 위해 애플리케이션에 연결할 수 없는 경우 사용량이 감소하지만 실패는 없습니다. 이 문서의 다음 섹션에서 이 데이터에 대한 샘플 쿼리를 참조하세요.
  • 시간당 실패율. 실패율이 급증하면 인증 메커니즘에 문제가 있음을 나타낼 수 있습니다. 실패율 측정은 사용자가 인증을 시도할 수 있는 경우에만 나타납니다. 사용자가 시도를 위해 액세스 권한을 얻을 수 없는 경우에는 실패가 없습니다.

쿼리 및 경고 구성

Azure Monitor에서 경고 규칙을 만들고 정기적으로 저장된 쿼리 또는 사용자 지정 로그 검색을 자동으로 실행할 수 있습니다. 사용량 또는 실패율이 지정된 임계값을 초과할 때 특정 그룹에 알림을 제공하는 경고를 구성할 수 있습니다.

다음 안내에 따라 그래프에 표시된 쿼리를 기준으로 이메일 경고를 만들 수 있습니다. 샘플 스크립트는 다음과 같은 경우 이메일 알림을 보냅니다.

  • 위의 시간별 사용량 그래프 예에 표시된 것처럼 성공적인 사용량은 이틀 전 같은 시간보다 90% 감소합니다.
  • 위의 시간별 고장률 그래프 예에서 볼 수 있듯이 고장률은 이틀 전 같은 시간보다 90% 증가합니다.

기본 쿼리를 구성하고 경고를 설정하려면 샘플 쿼리를 구성의 기초로 사용하여 다음 단계를 완료합니다. 쿼리 구조 설명은 이 섹션의 끝에 나타납니다. 로그 경고 관리에서 Azure Monitor를 사용하여 로그 경고를 만들고 보고 관리하는 방법을 알아봅니다.

  1. 통합 문서에서 다음 스크린샷과 같이 편집을 선택합니다. 그래프 오른쪽 상단에 있는 쿼리 아이콘을 선택합니다.

    통합 문서 편집을 보여 주는 스크린샷입니다.

  2. 다음 스크린샷과 같이 쿼리 로그를 봅니다.

    쿼리 로그를 보여주는 스크린샷입니다.

  3. 새 Kusto 쿼리에 대해 다음 샘플 스크립트 중 하나를 복사합니다.

  4. 창에 쿼리를 붙여넣습니다. 실행을 선택합니다. 다음 스크린샷에 표시된 대로 완료됨 메시지와 쿼리 결과를 찾습니다.

    쿼리 실행 결과를 보여 주는 스크린샷입니다.

  5. 쿼리를 강조 표시합니다. + 새 경고 규칙을 선택합니다.

    새 경고 규칙 화면을 보여 주는 스크린샷입니다.

  6. 경고 조건을 구성합니다. 다음 스크린샷 예에 표시된 것처럼 조건 섹션의 측정에서 측정값에 대해 테이블 행을 선택합니다. 집계 형식으로 개수를 선택합니다. 집계 세분성으로 2일을 선택합니다.

    경고 구성 화면을 보여 주는 스크린샷입니다.

    • 테이블 행. 반환된 행 수를 사용하여 Windows 이벤트 로그, Syslog 및 애플리케이션 예외와 같은 이벤트 작업을 수행할 수 있습니다.
    • 집계 형식. 개수가 적용된 데이터 포인트입니다.
    • 집계 세분성. 이 값은 평가 빈도에 적용되는 기간을 정의합니다.
  7. 경고 논리에서 스크린샷 예에 표시된 대로 매개 변수를 구성합니다.

    경고 논리 화면을 보여 주는 스크린샷.

    • 임계값: 0. 이 값은 모든 결과에 대해 경고합니다.
    • 평가 빈도: 1시간. 이 값은 이전 시간에 대해 평가 기간을 시간당 한 번으로 설정합니다.
  8. 작업 섹션에서 스크린샷 예에 표시된 대로 설정을 구성합니다.

    경고 규칙 만들기 화면을 보여 주는 스크린샷.

    • 작업 그룹 선택을 선택하고 경고를 받을 그룹을 추가합니다.
    • 작업 사용자 지정에서 이메일 경고를 선택합니다.
    • 제목 줄을 추가합니다.
  9. 세부 정보 섹션에서 스크린샷 예에 표시된 대로 설정을 구성합니다.

    세부 정보 섹션을 보여 주는 스크린샷.

    • 구독 이름과 설명을 추가합니다.
    • 경고를 추가할 리소스 그룹을 선택합니다.
    • 기본 심각도를 선택합니다.
    • 즉시 사용하도록 설정하려면 만들 때 사용을 선택합니다. 그렇지 않은 경우에는 작업 숨기기를 선택합니다.
  10. 검토 + 만들기 섹션에서 스크린샷 예에 표시된 대로 설정을 구성합니다.

    검토 + 만들기 섹션을 보여 주는 스크린샷.

  11. 저장을 선택합니다. 쿼리 이름을 입력합니다. 다른 이름으로 저장에서 쿼리를 선택합니다. 범주에서 경고을 선택합니다. 다시 저장을 선택합니다.

    쿼리 저장 단추를 보여 주는 스크린샷입니다.

쿼리 및 경고 세분화

효율성을 극대화하기 위해 쿼리 및 경고를 수정하려면 다음을 수행합니다.

  • 항상 경고를 테스트합니다.
  • 중요한 경고를 받으려면 경고 민감도와 빈도를 수정합니다. 경고가 너무 많이 표시되는 경우 관리자가 경고에 대해 둔감해지고 중요한 경고를 놓칠 수 있습니다.
  • 관리자의 이메일 클라이언트에서 허용된 보낸 사람 목록에 경고가 전송된 이메일을 추가합니다. 이 방식은 이메일 클라이언트의 스팸 필터로 인해 누락된 알림을 방지합니다.
  • 설계상, Azure Monitor의 경고 쿼리에는 지난 48시간 동안의 결과만 포함될 수 있습니다.

샘플 스크립트

실패율 증가에 대한 Kusto 쿼리

다음 쿼리에서는 실패율 증가를 검색합니다. 필요에 따라 하단에서 비율을 조정할 수 있습니다. 이는 어제 같은 시간의 트래픽과 비교하여 지난 시간의 트래픽 변화율을 나타냅니다. 0.5 결과는 트래픽의 50% 차이를 나타냅니다.

let today = SigninLogs
| where TimeGenerated > ago(1h) // Query failure rate in the last hour
| project TimeGenerated, UserPrincipalName, AppDisplayName, status = case(Status.errorCode == "0", "success", "failure")
// Optionally filter by a specific application
//| where AppDisplayName == **APP NAME**
| summarize success = countif(status == "success"), failure = countif(status == "failure") by bin(TimeGenerated, 1h) // hourly failure rate
| project TimeGenerated, failureRate = (failure * 1.0) / ((failure + success) * 1.0)
| sort by TimeGenerated desc
| serialize rowNumber = row_number();
let yesterday = SigninLogs
| where TimeGenerated between((ago(1h) – totimespan(1d))..(now() – totimespan(1d))) // Query failure rate at the same time yesterday
| project TimeGenerated, UserPrincipalName, AppDisplayName, status = case(Status.errorCode == "0", "success", "failure")
// Optionally filter by a specific application
//| where AppDisplayName == **APP NAME**
| summarize success = countif(status == "success"), failure = countif(status == "failure") by bin(TimeGenerated, 1h) // hourly failure rate at same time yesterday
| project TimeGenerated, failureRateYesterday = (failure * 1.0) / ((failure + success) * 1.0)
| sort by TimeGenerated desc
| serialize rowNumber = row_number();
today
| join (yesterday) on rowNumber // join data from same time today and yesterday
| project TimeGenerated, failureRate, failureRateYesterday
// Set threshold to be the percent difference in failure rate in the last hour as compared to the same time yesterday
// Day variable is the number of days since the previous Sunday. Optionally ignore results on Sat, Sun, and Mon because large variability in traffic is expected.
| extend day = dayofweek(now())
| where day != time(6.00:00:00) // exclude Sat
| where day != time(0.00:00:00) // exclude Sun
| where day != time(1.00:00:00) // exclude Mon
| where abs(failureRate – failureRateYesterday) > 0.5

사용량 감소에 대한 Kusto 쿼리

다음 쿼리에서는 지난 시간의 트래픽을 어제의 트래픽과 동시에 비교합니다. 토요일, 일요일, 월요일은 동시에 전날의 트래픽 변동폭이 클 것으로 예상되므로 제외됩니다.

필요에 따라 하단에서 비율을 조정할 수 있습니다. 이는 어제 같은 시간의 트래픽과 비교하여 지난 시간의 트래픽 변화율을 나타냅니다. 0.5 결과는 트래픽의 50% 차이를 나타냅니다. 비즈니스 운영 모델에 맞게 이러한 값을 조정합니다.

Let today = SigninLogs // Query traffic in the last hour
| where TimeGenerated > ago(1h)
| project TimeGenerated, AppDisplayName, UserPrincipalName
// Optionally filter by AppDisplayName to scope query to a single application
//| where AppDisplayName contains "Office 365 Exchange Online"
| summarize users = dcount(UserPrincipalName) by bin(TimeGenerated, 1hr) // Count distinct users in the last hour
| sort by TimeGenerated desc
| serialize rn = row_number();
let yesterday = SigninLogs // Query traffic at the same hour yesterday
| where TimeGenerated between((ago(1h) – totimespan(1d))..(now() – totimespan(1d))) // Count distinct users in the same hour yesterday
| project TimeGenerated, AppDisplayName, UserPrincipalName
// Optionally filter by AppDisplayName to scope query to a single application
//| where AppDisplayName contains "Office 365 Exchange Online"
| summarize usersYesterday = dcount(UserPrincipalName) by bin(TimeGenerated, 1hr)
| sort by TimeGenerated desc
| serialize rn = row_number();
today
| join // Join data from today and yesterday together
(
yesterday
)
on rn
// Calculate the difference in number of users in the last hour compared to the same time yesterday
| project TimeGenerated, users, usersYesterday, difference = abs(users – usersYesterday), max = max_of(users, usersYesterday)
| extend ratio = (difference * 1.0) / max // Ratio is the percent difference in traffic in the last hour as compared to the same time yesterday
// Day variable is the number of days since the previous Sunday. Optionally ignore results on Sat, Sun, and Mon because large variability in traffic is expected.
| extend day = dayofweek(now())
| where day != time(6.00:00:00) // exclude Sat
| where day != time(0.00:00:00) // exclude Sun
| where day != time(1.00:00:00) // exclude Mon
| where ratio > 0.7 // Threshold percent difference in sign-in traffic as compared to same hour yesterday

경고 관리를 위한 프로세스 만들기

쿼리 및 경고를 설정한 후 경고를 관리하기 위한 비즈니스 프로세스를 만듭니다.

  • 누가 통합 문서를 언제 모니터링하나요?
  • 경고가 발생하면 누가 조사하나요?
  • 통신 요구 사항은 무엇인가요? 커뮤니케이션은 누가 만들고 누가 받나요?
  • 가동 중단이 발생하면 어떤 비즈니스 프로세스가 적용되나요?

다음 단계

통합 문서에 대해 자세히 알아보기