Microsoft Sentinel CCF 푸시 커넥터(미리 보기) - 시작 가이드

이 가이드는 CCF(Codeless Connector Framework) 푸시(미리 보기)를 사용하여 Microsoft Sentinel용 푸시 기반 코드리스 커넥터를 이해하고, 빌드하고, 배포하는 데 도움이 됩니다.

CCF 푸시란?

CCF 푸시 커넥터를 사용하면 애플리케이션이 실시간으로 Microsoft Sentinel에 직접 보안 이벤트를 보낼 수 있습니다. API에서 데이터를 주기적으로 가져오는 기존 폴링 기반 커넥터와 달리 푸시 커넥터를 사용하면 시스템에서 이벤트가 발생할 때 Sentinel에 데이터를 푸시할 수 있습니다.

CCF 푸시는 다음과 같은 몇 가지 주요 이점을 제공합니다.

  • 애플리케이션 제어 데이터 흐름: 애플리케이션은 데이터를 보내는 시기와 방법을 제어하여 지능형 일괄 처리 전략과 최적화된 네트워크 사용을 가능하게 합니다.
  • 실시간 수집: 폴링 간격을 기다리지 않고 이벤트가 발생하면 즉시 데이터를 보냅니다.
  • 간소화된 아키텍처: Sentinel이 폴링할 API 엔드포인트를 유지할 필요가 없습니다.
  • 템플릿 기반 프로비저닝: 배포는 DCR, 사용자 지정 테이블, Entra 애플리케이션 등록 및 클라이언트 비밀에 대한 ARM 템플릿을 만듭니다. 전송 애플리케이션에서 구성할 연결 세부 정보를 받습니다.
  • 보안 인증: 보안 데이터 제출을 위해 OAuth 2.0과 함께 Microsoft Entra 애플리케이션을 사용합니다.

사전 요구 사항

  • 시작하기 전에 패키징 도구에 대한 Azure-Sentinel GitHub 리포지토리에 액세스할 수 있어야 합니다.
  • Microsoft Entra 권한:
    • Microsoft Entra ID에서 앱 등록을 만들 수 있는 권한입니다. 일반적으로 Entra ID 애플리케이션 개발자 역할 이상이 필요합니다.
    • 비밀을 사용하여 애플리케이션을 만들 수 있는 권한입니다. 이 권한을 부여하지 않으면 보안상의 이유로 커넥터가 실패합니다.
    • 게시자는 Microsoft Entra 애플리케이션에서 토큰을 검색할 적절한 역할이 있어야 합니다. 이러한 토큰은 커넥터가 궁극적으로 데이터를 푸시하는 엔드포인트인 DCE(데이터 수집 엔드포인트)에 대한 요청을 인증하는 데 필요합니다. 공급자가 토큰을 검색할 수 없는 경우 DCE로 데이터를 보낼 수 없습니다.
  • Microsoft Azure 권한:
    • DCR(데이터 수집 규칙)에 모니터링 메트릭 게시자 역할을 할당할 수 있는 권한입니다. 일반적으로 AZURE RBAC 소유자 또는 사용자 액세스 관리자 역할이 필요합니다.

CCF 푸시 작동 방식

푸시 모델 및 끌어오기 모델

푸시 및 끌어오기 데이터 수집 모델의 차이를 이해하면 시나리오에 적합한 커넥터 유형을 선택하는 데 도움이 됩니다.

CCF 풀 커넥터 - 폴링 기반:

끌어오기 모델에서 Microsoft Sentinel은 주기적으로 API를 폴링하여 데이터를 검색합니다.

  • Microsoft Sentinel은 구성된 일정에 따라 데이터 원본 API에 대한 연결을 시작합니다.
  • 데이터는 일반적으로 5분과 같이 정기적인 폴링 간격으로 도착합니다.
  • 공개적으로 액세스할 수 있는 API 엔드포인트를 유지 관리해야 합니다.
  • Sentinel의 폴링 인프라는 데이터 수집 프로세스를 관리합니다.

CCF 푸시 커넥터 - 이벤트 기반:

푸시 모델에서 애플리케이션은 Microsoft Sentinel에 직접 데이터를 보냅니다.

  • 애플리케이션은 이벤트가 발생할 때 데이터 제출을 시작합니다.
  • 이벤트가 생성되면 데이터가 거의 실시간으로 도착합니다.
  • API 엔드포인트를 유지 관리할 필요가 없습니다.
  • 애플리케이션은 일괄 처리, 타이밍 및 데이터 흐름 최적화를 제어합니다.

푸시 데이터 흐름

CCF 푸시 데이터 흐름은 다음 5가지 주요 단계로 구성됩니다.

  1. Microsoft Sentinel에 커넥터를 배포합니다.

  2. Azure는 다음 리소스를 자동으로 만듭니다.

    • 자격 증명이 있는 Microsoft Entra 애플리케이션
    • DCR(데이터 수집 규칙) - 데이터를 처리하는 방법을 정의합니다.
    • DCE(데이터 수집 엔드포인트) - 데이터를 보내는 URL
    • 사용자 지정 로그 테이블 - 데이터가 저장되는 위치
    • 역할 할당 - Entra 앱에 대한 권한
  3. 다음과 같은 연결 세부 정보가 표시됩니다.

    • 임차인 ID
    • 애플리케이션(클라이언트) ID
    • 클라이언트 암호
    • DCE URI(엔드포인트 URL)
    • DCR 변경할 수 없는 ID
    • 스트림 이름
  4. 애플리케이션은 다음 데이터를 보냅니다.

    • CCF에서 생성된 Entra 앱 자격 증명을 사용하여 OAuth 2.0 토큰을 가져옵니다. 자세한 내용은 OAuth 2.0 클라이언트 자격 증명 흐름을 참조하세요.
    • 테이블 스키마와 일치하는 JSON으로 이벤트 서식 지정
    • DCE 엔드포인트에 데이터를 POST합니다.
  5. Azure는 데이터를 처리하고 저장합니다.

    • DCR은 데이터를 변환합니다(선택적 KQL 변환).
    • 데이터는 Log Analytics의 사용자 지정 테이블에 기록됩니다.
    • 이 데이터는 Sentinel의 쿼리, 분석 및 경고에 사용할 수 있습니다.

CCF 푸시 아티팩트

CCF 푸시 커넥터 솔루션은 다음 네 가지 주요 구성 요소로 구성됩니다.

  • 사용자 지정 테이블 정의
  • DCR(데이터 수집 규칙)
  • 커넥터 정의(UI)
  • 푸시 커넥터 구성

사용자 지정 테이블 정의

내용: Log Analytics에서 데이터의 구조를 정의하는 스키마입니다.

핵심 요구 사항:

Example:

{
  "name": "ContosoSecurityAlerts_CL",
  "type": "Microsoft.OperationalInsights/workspaces/tables",
  "apiVersion": "2025-07-01",
  "properties": {
     "schema": {
        "name": "ContosoSecurityAlerts_CL",
        "columns": [
          {
             "name": "TimeGenerated",
             "type": "datetime"
          },
          {
             "name": "EventSeverity",
             "type": "string"
          },
          {
             "name": "EventType",
             "type": "string"
          },
          {
             "name": "UserName",
             "type": "string"
          },
          {
             "name": "SourceIP",
             "type": "string"
          },
          {
             "name": "DeviceId",
             "type": "string"
          },
          {
             "name": "AlertMessage",
             "type": "string"
          }
        ]
     }
  }
}

DCR(데이터 수집 규칙)

내용: Azure Monitor에서 데이터를 수집하고 처리하는 방법을 정의합니다. 자세한 내용은 Azure Monitor의 데이터 수집 규칙을 참조하세요.

기능 설명:

  • 입력 스트림 이름(데이터를 보낼 때 앱에서 사용하는 이름)을 지정합니다.
  • 데이터 셰이프 및 보강을 위한 선택적 KQL 변환 정의
  • 대상 테이블로 데이터 라우팅
  • DCE(데이터 수집 엔드포인트)에 대한 링크

주요 구성 요소:

  • streamDeclarations: 들어오는 데이터의 구조를 정의합니다(앱에서 보내는 것과 일치해야 합니다).
  • destinations: 데이터가 어디로 가는지(Log Analytics 작업 영역)
  • dataFlows: 입력 스트림에서 출력 테이블로 변환 파이프라인
  • dataCollectionEndpointId: 데이터 수집을 위한 DCE에 대한 링크

Example:

{
  "name": "ContosoSecurityAlertsPushDCR",
  "apiVersion": "2021-09-01-preview",
  "type": "Microsoft.Insights/dataCollectionRules",
  "location": "[parameters('workspace-location')]",
  "properties": {
     "streamDeclarations": {
        "Custom-ContosoSecurityAlerts": {
          "columns": [
             {
                "name": "EventSeverity",
                "type": "string"
             },
             {
                "name": "EventType",
                "type": "string"
             },
             {
                "name": "UserName",
                "type": "string"
             },
             {
                "name": "SourceIP",
                "type": "string"
             },
             {
                "name": "DeviceId",
                "type": "string"
             },
             {
                "name": "AlertMessage",
                "type": "string"
             }
          ]
        }
     },
     "destinations": {
        "logAnalytics": [
          {
             "workspaceResourceId": "[variables('workspaceResourceId')]",
             "name": "clv2ws1"
          }
        ]
     },
     "dataFlows": [
        {
          "streams": [
             "Custom-ContosoSecurityAlerts"
          ],
          "destinations": [
             "clv2ws1"
          ],
          "transformKql": "source | extend TimeGenerated = now()",
          "outputStream": "Custom-ContosoSecurityAlerts_CL"
        }
     ],
     "dataCollectionEndpointId": "[concat('/subscriptions/',parameters('subscription'),'/resourceGroups/',parameters('resourceGroupName'),'/providers/Microsoft.Insights/dataCollectionEndpoints/',parameters('workspace'))]"
  }
}

중요합니다

  • 스트림 이름은 접두사로 Custom- 시작해야 합니다.
  • 단순히 transformKql"source" 통과용이거나 데이터 변환을 위한 KQL 논리를 포함할 수 있습니다.
  • outputStream 는 테이블 이름과 Custom- 접두사 및 _CL 접미사를 일치시켜야 합니다.

커넥터 정의(UI)

커넥터 정의는 커넥터가 Microsoft Sentinel 데이터 커넥터 갤러리에 표시되는 방식을 제어합니다. 자세한 내용은 데이터 커넥터 정의 API 참조를 참조하세요.

커넥터 정의에는 다음이 포함됩니다.

  • 커넥터 제목, 설명 및 브랜딩
  • 필수 구성 요소 및 필요한 권한(예: 작업 영역 액세스 및 Entra 권한)
  • 배포에 대한 지침 단계
  • 사용자에게 연결 세부 정보를 표시하기 위한 UI 컨트롤

주요 UI 요소:

  • DeployPushConnectorButton: 자동화된 리소스 배포를 트리거합니다.
  • CopyableLabel: 배포 후 연결 세부 정보를 표시합니다(매개 변수 사용 fillWith ).
  • Markdown: 형식이 지정된 지침 및 컨텍스트를 제공합니다.
  • IsConnectedQuery: 최근 데이터를 기반으로 커넥터 연결의 유효성을 검사합니다.

예제 구조(명확성을 위해 축약됨):

{
    "name": "ContosoSecurityAlertsPush",
    "apiVersion": "2022-09-01-preview",
    "type": "Microsoft.SecurityInsights/dataConnectorDefinitions",
    "location": "[parameters('workspace-location')]",
    "kind": "Customizable",
    "properties": {
        "connectorUiConfig": {
            "id": "ContosoSecurityAlertsPush",
            "title": "Contoso Security Alerts (Push)",
            "publisher": "Contoso Corporation",
            "descriptionMarkdown": "The [Contoso Security Alerts](https://www.contoso.com/) connector provides the capability to push real-time security alerts from your Contoso application directly into Microsoft Sentinel using the Codeless Connector Framework (CCF) Push pattern. This connector ingests alert severity, event types, user information, and network details into a custom Log Analytics table for analysis, alerting, and visualization.",
            "graphQueries": [
                {
                    "metricName": "Security Alerts",
                    "legend": "ContosoSecurityAlerts_CL",
                    "baseQuery": "ContosoSecurityAlerts_CL"
                }
            ],
            "sampleQueries": [
                {
                    "description": "All security alerts",
                    "query": "ContosoSecurityAlerts_CL\n | sort by TimeGenerated desc"
                },
                {
                    "description": "Critical and High severity alerts",
                    "query": "ContosoSecurityAlerts_CL\n | where EventSeverity in ('Critical', 'High')\n | sort by TimeGenerated desc"
                }
            ],
            "dataTypes": [
                {
                    "name": "ContosoSecurityAlerts_CL",
                    "lastDataReceivedQuery": "ContosoSecurityAlerts_CL\n| summarize Time = max(TimeGenerated)\n| where isnotempty(Time)"
                }
            ],
            "connectivityCriteria": [
                {
                    "type": "IsConnectedQuery",
                    "value": [
                        "ContosoSecurityAlerts_CL\n| summarize LastLogReceived = max(TimeGenerated)\n| project IsConnected = LastLogReceived > ago(7d)"
                    ]
                }
            ],
            "availability": {
                "status": 1
            },
            "permissions": {
                "resourceProvider": [
                    {
                        "provider": "Microsoft.OperationalInsights/workspaces",
                        "permissionsDisplayText": "read and write permissions are required.",
                        "providerDisplayName": "Workspace",
                        "scope": "Workspace",
                        "requiredPermissions": {
                            "write": true,
                            "read": true,
                            "delete": true
                        }
                    }
                ],
                "customs": [
                    {
                        "name": "Microsoft Entra",
                        "description": "Permission to create an app registration in Microsoft Entra ID. Typically requires Entra ID Application Developer role or higher."
                    },
                    {
                        "name": "Microsoft Azure",
                        "description": "Permission to assign Monitoring Metrics Publisher role on data collection rule (DCR). Typically requires Azure RBAC Owner or User Access Administrator role."
                    }
                ]
            },
            "instructionSteps": [
                {
                    "title": "1. Create ARM Resources and Provide the Required Permissions",
                    "description": "This connector enables your Contoso application to push security alerts directly to Microsoft Sentinel via the Azure Monitor Ingestion API.",
                    "instructions": [
                        {
                            "type": "Markdown",
                            "parameters": {
                                "content": "#### Automated Configuration and Secure Data Ingestion with Entra Application \nClicking on \"Deploy\" will trigger the creation of a Log Analytics table and a Data Collection Rule (DCR). \nIt will then create an Entra application, link the DCR to it, and set the entered secret in the application. This setup enables data to be sent securely to the DCR using an Entra token."
                            }
                        },
                        {
                            "type": "DeployPushConnectorButton",
                            "parameters": {
                                "label": "Deploy Contoso Push connector resources",
                                "applicationDisplayName": "Contoso Security Alerts Push Connector Application"
                            }
                        }
                    ]
                },
                {
                    "title": "2. Configure Your Contoso Application",
                    "description": "Use the following parameters to configure your Contoso application to push security alerts to the workspace.",
                    "instructions": [
                        {
                            "type": "CopyableLabel",
                            "parameters": {
                                "label": "Tenant ID (Directory ID)",
                                "fillWith": [
                                    "TenantId"
                                ]
                            }
                        },
                        {
                            "type": "CopyableLabel",
                            "parameters": {
                                "label": "Entra App Registration Application ID",
                                "fillWith": [
                                    "ApplicationId"
                                ],
                                "placeholder": "Deploy push connector to get the App Registration Application ID"
                            }
                        },
                        {
                            "type": "CopyableLabel",
                            "parameters": {
                                "label": "Entra App Registration Secret",
                                "fillWith": [
                                    "ApplicationSecret"
                                ],
                                "placeholder": "Deploy push connector to get the App Registration Secret"
                            }
                        },
                        {
                            "type": "CopyableLabel",
                            "parameters": {
                                "label": "Data Collection Endpoint Uri",
                                "fillWith": [
                                    "DataCollectionEndpoint"
                                ],
                                "placeholder": "Deploy push connector to get the Data Collection Endpoint Uri"
                            }
                        },
                        {
                            "type": "CopyableLabel",
                            "parameters": {
                                "label": "Data Collection Rule Immutable ID",
                                "fillWith": [
                                    "DataCollectionRuleId"
                                ],
                                "placeholder": "Deploy push connector to get the Data Collection Rule Immutable ID"
                            }
                        },
                        {
                            "type": "CopyableLabel",
                            "parameters": {
                                "label": "Stream Name",
                                "value": "Custom-ContosoSecurityAlerts"
                            }
                        },
                        {
                            "type": "Markdown",
                            "parameters": {
                                "content": "#### Configure Contoso Application\nUpdate your Contoso application configuration with the above credentials to enable security alert push to Microsoft Sentinel.\n\nExample configuration:\njson\n{\n \"azure\": {\n \"tenant_id\": \"<Tenant ID>\",\n \"client_id\": \"<Application ID>\",\n \"client_secret\": \"<Application Secret>\",\n \"dce_endpoint\": \"<Data Collection Endpoint Uri>\",\n \"dcr_immutable_id\": \"<Data Collection Rule Immutable ID>\",\n \"stream_name\": \"Custom-ContosoSecurityAlerts\"\n }\n}\n"
                            }
                        }
                    ]
                }
            ]
        }
    }
}

중요합니다

  • idconnectorUiConfig는 고유해야 하며 데이터 커넥터 구성에서의 참조와 일치해야 합니다.
  • 프로덕션 커넥터(최근 데이터의 유효성 검사) 또는 IsConnectedQuery 더 간단한 유효성 검사에 사용합니다hasDataConnectors.
  • 매개 fillWith 변수는 CopyableLabel 배포 후에 자동으로 채워집니다.
  • 스트림 이름과 같은 고정 값은 대신 매개 변수valuefillWith 사용합니다.

푸시 커넥터 구성

푸시 커넥터 구성은 커넥터 정의를 배포된 리소스에 연결하는 데이터 커넥터 인스턴스입니다.

푸시 커넥터 구성

  • 커넥터 정의(UI)를 배포된 DCR 및 Entra 앱에 연결
  • 인증 세부 정보(앱 ID, 서비스 주체 ID)를 저장합니다.
  • DCR 구성 기록(엔드포인트, 변경할 수 없는 ID, 스트림 이름)
  • UI가 사용자에게 연결 세부 정보를 검색하고 표시할 수 있도록 합니다.

키 속성:

  • connectorDefinitionName: 커넥터 정의와 id 일치해야 합니다.
  • dcrConfig: DCR 엔드포인트, 규칙 ID 및 스트림 이름을 포함합니다.
  • auth: Entra 애플리케이션 ID 및 서비스 주체 ID를 포함합니다.
  • kind: 푸시 커넥터의 경우 "푸시"여야 합니다.

Example:

{
  "name": "ContosoSecurityAlertsPushDCR",
  "apiVersion": "2021-09-01-preview",
  "type": "Microsoft.Insights/dataCollectionRules",
  "location": "[parameters('workspace-location')]",
  "properties": {
    "streamDeclarations": {
      "Custom-ContosoSecurityAlerts": {
        "columns": [
          {
            "name": "EventSeverity",
            "type": "string"
          },
          {
            "name": "EventType",
            "type": "string"
          },
          {
            "name": "UserName",
            "type": "string"
          },
          {
            "name": "SourceIP",
            "type": "string"
          },
          {
            "name": "DeviceId",
            "type": "string"
          },
          {
            "name": "AlertMessage",
            "type": "string"
          }
        ]
      }
    },
    "destinations": {
      "logAnalytics": [
        {
          "workspaceResourceId": "[variables('workspaceResourceId')]",
          "name": "clv2ws1"
        }
      ]
    },
    "dataFlows": [
      {
        "streams": [
          "Custom-ContosoSecurityAlerts"
        ],
        "destinations": [
          "clv2ws1"
        ],
        "transformKql": "source | extend TimeGenerated = now()",
        "outputStream": "Custom-ContosoSecurityAlerts_CL"
      }
    ],
    "dataCollectionEndpointId": "[concat('/subscriptions/',parameters('subscription'),'/resourceGroups/',parameters('resourceGroupName'),'/providers/Microsoft.Insights/dataCollectionEndpoints/',parameters('workspace'))]"
  }
}

중요합니다

  • 커넥터 connectorDefinitionName 정의 id와 정확히 일치해야 합니다.
  • DCR streamName 에 선언된 스트림과 일치해야 합니다.
  • 이 리소스는 배포 중에 사용자가 DeployPushConnector 단추를 선택하면 자동으로 만들어집니다.

첫 번째 푸시 커넥터 빌드

이 예제에서는 애플리케이션에서 Sentinel로 보안 경고를 보내는 간단한 푸시 커넥터를 빌드합니다.

목표: 애플리케이션에서 Sentinel로 실시간으로 보안 경고 보내기

애플리케이션은 이벤트 구조를 보냅니다.

{
  "TimeGenerated": "2025-11-21T10:30:00Z",
  "EventSeverity": "Medium",
  "EventType": "LoginAlert",
  "UserName": "alice@contoso.com",
  "SourceIP": "192.168.1.100",
  "DeviceId": "device-12345",
  "AlertMessage": "Multiple failed login attempts detected"
}

푸시 커넥터를 만드는 단계별 가이드

  1. Azure-Sentinel 리포지토리 복제

    포크한 다음, 공식 Azure-Sentinel 리포지토리를 로컬 컴퓨터에 복제합니다. 이 리포지토리는 패키징 도구를 포함하고 표준 솔루션 구조를 제공합니다.

    1. 리포지토리 복제
      git clone https://github.com/<YOUR_FORK>/Azure-Sentinel.git

    2. 솔루션 디렉터리로 이동합니다. cd Azure-Sentinel/Solutions
      리포지토리 구조에는 다음이 포함됩니다.

    • 도구/Create-Azure-Sentinel-Solution/V3/
    • createSolutionV3.ps1 패키징 스크립트를 포함합니다.
    • 솔루션/ 커넥터 솔루션을 만들 위치
  2. 솔루션 폴더 구조 만들기 표준 명명 규칙에 따라 Solutions/폴더 내에 새 솔루션 디렉터리를 만듭니다. 솔루션 디렉터리 만들기(Azure-Sentinel/Solutions에서)

    mkdir ContosoSecurityAlerts
    cd ContosoSecurityAlerts
    mkdir Data
    mkdir "Data Connectors"
    mkdir "Data Connectors/ContosoSecurityAlerts_ccf"
    

    폴더 구조는 다음과 같습니다.

    Azure-Sentinel/
     └-• 솔루션/
        └ ContosoSecurityAlerts/
            ├── 데이터/
            └ 데이터 커넥터/
                └ContosoSecurityAlerts_ccf/

  3. 테이블 정의

    ContosoSecurityAlerts_ccf 폴더에서 사용자 지정 테이블 정의를 사용하여 table.json 파일을 만듭니다.

    {
      "name": "ContosoSecurityAlerts_CL",
      "type": "Microsoft.OperationalInsights/workspaces/tables",
      "apiVersion": "2025-07-01",
      "properties": {
        "schema": {
          "name": "ContosoSecurityAlerts_CL",
          "columns": [
            {
              "name": "TimeGenerated",
              "type": "datetime"
            },
            {
              "name": "EventSeverity",
              "type": "string"
            },
            {
              "name": "EventType",
              "type": "string"
            },
            {
              "name": "UserName",
              "type": "string"
            },
            {
              "name": "SourceIP",
              "type": "string"
            },
            {
              "name": "DeviceId",
              "type": "string"
            },
            {
              "name": "AlertMessage",
              "type": "string"
            }
          ]
        }
      }
    }
    
  4. DCR 만들기

    ContosoSecurityAlerts_ccf 폴더에서 입력 스트림을 정의하고 데이터를 테이블로 라우팅하는 DCR.json 파일을 만듭니다.

    {
      "name": "ContosoSecurityAlertsPushDCR",
      "apiVersion": "2021-09-01-preview",
      "type": "Microsoft.Insights/dataCollectionRules",
      "location": "[parameters('workspace-location')]",
      "properties": {
        "streamDeclarations": {
          "Custom-ContosoSecurityAlerts": {
            "columns": [
              {
                "name": "EventSeverity",
                "type": "string"
              },
              {
                "name": "EventType",
                "type": "string"
              },
              {
                "name": "UserName",
                "type": "string"
              },
              {
                "name": "SourceIP",
                "type": "string"
              },
              {
                "name": "DeviceId",
                "type": "string"
              },
              {
                "name": "AlertMessage",
                "type": "string"
              }
            ]
          }
        },
        "destinations": {
          "logAnalytics": [
            {
              "workspaceResourceId": "[variables('workspaceResourceId')]",
              "name": "clv2ws1"
            }
          ]
        },
        "dataFlows": [
          {
            "streams": [
              "Custom-ContosoSecurityAlerts"
            ],
            "destinations": [
              "clv2ws1"
            ],
            "transformKql": "source | extend TimeGenerated = now()",
            "outputStream": "Custom-ContosoSecurityAlerts_CL"
          }
        ],
        "dataCollectionEndpointId": "[concat('/subscriptions/',parameters('subscription'),'/resourceGroups/',parameters('resourceGroupName'),'/providers/Microsoft.Insights/    dataCollectionEndpoints/',parameters('workspace'))]"
      }
    }
    
  5. 커넥터 정의 만들기

    ContosoSecurityAlerts_ccf 폴더에서 사용자가 Sentinel에서 커넥터와 상호 작용하는 방법을 정의하는 connectorDefinition.json 파일을 만듭니다.

    {
        "name": "ContosoSecurityAlertsPush",
        "apiVersion": "2022-09-01-preview",
        "type": "Microsoft.SecurityInsights/dataConnectorDefinitions",
        "location": "[parameters('workspace-location')]",
        "kind": "Customizable",
        "properties": {
            "connectorUiConfig": {
                "id": "ContosoSecurityAlertsPush",
                "title": "Contoso Security Alerts (Push)",
                "publisher": "Contoso Corporation",
                "descriptionMarkdown": "The [Contoso Security Alerts](https://www.contoso.com/) connector provides the capability to push real-time security alerts from your   Contoso application directly into Microsoft Sentinel using the Codeless Connector Framework (CCF) Push pattern. This connector ingests alert severity, event  types, user information, and network details into a custom Log Analytics table for analysis, alerting, and visualization.",
                "graphQueries": [
                    {
                        "metricName": "Security Alerts",
                        "legend": "ContosoSecurityAlerts_CL",
                        "baseQuery": "ContosoSecurityAlerts_CL"
                    }
                ],
                "sampleQueries": [
                    {
                        "description": "All security alerts",
                        "query": "ContosoSecurityAlerts_CL\n | sort by TimeGenerated desc"
                    },
                    {
                        "description": "Critical and High severity alerts",
                        "query": "ContosoSecurityAlerts_CL\n | where EventSeverity in ('Critical', 'High')\n | sort by TimeGenerated desc"
                    }
                ],
                "dataTypes": [
                    {
                        "name": "ContosoSecurityAlerts_CL",
                        "lastDataReceivedQuery": "ContosoSecurityAlerts_CL\n| summarize Time = max(TimeGenerated)\n| where isnotempty(Time)"
                    }
                ],
                "connectivityCriteria": [
                    {
                        "type": "IsConnectedQuery",
                        "value": [
                            "ContosoSecurityAlerts_CL\n| summarize LastLogReceived = max(TimeGenerated)\n| project IsConnected = LastLogReceived > ago(7d)"
                        ]
                    }
                ],
                "availability": {
                    "status": 1
                },
                "permissions": {
                    "resourceProvider": [
                        {
                            "provider": "Microsoft.OperationalInsights/workspaces",
                            "permissionsDisplayText": "read and write permissions are required.",
                            "providerDisplayName": "Workspace",
                            "scope": "Workspace",
                            "requiredPermissions": {
                                "write": true,
                                "read": true,
                                "delete": true
                            }
                        }
                    ],
                    "customs": [
                        {
                            "name": "Microsoft Entra",
                            "description": "Permission to create an app registration in Microsoft Entra ID. Typically requires Entra ID Application Developer role or higher."
                        },
                        {
                            "name": "Microsoft Azure",
                            "description": "Permission to assign Monitoring Metrics Publisher role on data collection rule (DCR). Typically requires Azure RBAC Owner or User   Access Administrator role."
                        }
                    ]
                },
                "instructionSteps": [
                    {
                        "title": "1. Create ARM Resources and Provide the Required Permissions",
                        "description": "This connector enables your Contoso application to push security alerts directly to Microsoft Sentinel via the Azure Monitor Ingestion  API.",
                        "instructions": [
                            {
                                "type": "Markdown",
                                "parameters": {
                                    "content": "#### Automated Configuration and Secure Data Ingestion with Entra Application \nClicking on \"Deploy\" will trigger the creation    of a Log Analytics table and a Data Collection Rule (DCR). \nIt will then create an Entra application, link the DCR to it, and set the     entered secret in the application. This setup enables data to be sent securely to the DCR using an Entra token."
                                }
                            },
                            {
                                "type": "DeployPushConnectorButton",
                                "parameters": {
                                    "label": "Deploy Contoso Push connector resources",
                                    "applicationDisplayName": "Contoso Security Alerts Push Connector Application"
                                }
                            }
                        ]
                    },
                    {
                        "title": "2. Configure Your Contoso Application",
                        "description": "Use the following parameters to configure your Contoso application to push security alerts to the workspace.",
                        "instructions": [
                            {
                                "type": "CopyableLabel",
                                "parameters": {
                                    "label": "Tenant ID (Directory ID)",
                                    "fillWith": [
                                        "TenantId"
                                    ]
                                }
                            },
                            {
                                "type": "CopyableLabel",
                                "parameters": {
                                    "label": "Entra App Registration Application ID",
                                    "fillWith": [
                                        "ApplicationId"
                                    ],
                                    "placeholder": "Deploy push connector to get the App Registration Application ID"
                                }
                            },
                            {
                                "type": "CopyableLabel",
                                "parameters": {
                                    "label": "Entra App Registration Secret",
                                    "fillWith": [
                                        "ApplicationSecret"
                                    ],
                                    "placeholder": "Deploy push connector to get the App Registration Secret"
                                }
                            },
                            {
                                "type": "CopyableLabel",
                                "parameters": {
                                    "label": "Data Collection Endpoint Uri",
                                    "fillWith": [
                                        "DataCollectionEndpoint"
                                    ],
                                    "placeholder": "Deploy push connector to get the Data Collection Endpoint Uri"
                                }
                            },
                            {
                                "type": "CopyableLabel",
                                "parameters": {
                                    "label": "Data Collection Rule Immutable ID",
                                    "fillWith": [
                                        "DataCollectionRuleId"
                                    ],
                                    "placeholder": "Deploy push connector to get the Data Collection Rule Immutable ID"
                                }
                            },
                            {
                                "type": "CopyableLabel",
                                "parameters": {
                                    "label": "Stream Name",
                                    "value": "Custom-ContosoSecurityAlerts"
                                }
                            },
                            {
                                "type": "Markdown",
                                "parameters": {
                                    "content": "#### Configure Contoso Application\nUpdate your Contoso application configuration with the above credentials to enable security     alert push to Microsoft Sentinel.\n\nExample configuration:\njson\n{\n \"azure\": {\n \"tenant_id\": \"<Tenant ID>\",\n \"client_id\":  \"<Application ID>\",\n \"client_secret\": \"<Application Secret>\",\n \"dce_endpoint\": \"<Data Collection Endpoint Uri>\",\n   \"dcr_immutable_id\": \"<Data Collection Rule Immutable ID>\",\n \"stream_name\": \"Custom-ContosoSecurityAlerts\"\n }\n}\n"
                                }
                            }
                        ]
                    }
                ]
            }
        }
    }
    
  6. 데이터 커넥터 구성 만들기

    ContosoSecurityAlerts_ccf 폴더에서 커넥터 정의를 배포된 리소스에 연결하는 dataConnector.json 파일을 만듭니다.

    {
      "name": "ContosoSecurityAlertsPushConnectorPolling",
      "apiVersion": "2024-09-01",
      "type": "Microsoft.SecurityInsights/dataConnectors",
      "kind": "Push",
      "properties": {
        "connectorDefinitionName": "ContosoSecurityAlertsPush",
        "dcrConfig": {
          "streamName": "Custom-ContosoSecurityAlerts",
          "dataCollectionEndpoint": "[[parameters('dcrConfig').dataCollectionEndpoint]",
          "dataCollectionRuleImmutableId": "[[parameters('dcrConfig').dataCollectionRuleImmutableId]"
        },
        "auth": {
          "type": "Push",
          "AppId": "[[parameters('auth').appId]",
          "ServicePrincipalId": "[[parameters('auth').servicePrincipalId]"
        },
        "request": {
          "RetryCount": 1
        },
        "response": {
          "eventsJsonPaths": [
            "$"
          ]
        }
      }
    }
    
  7. 솔루션 메타데이터 파일 만들기

    1. Solution_ContosoSecurityAlerts.json 파일을 데이터 폴더에 만들고, Solution_ContosoSecurityAlerts.json에 당신의 해결책 세부 정보를 포함하세요.

      {
           "Name": "ContosoSecurityAlerts",
           "Author": "Contoso Corporation - support@contoso.com",
           "Logo": "<svg width=\"75px\" height=\"75px\" viewBox=\"0 0 75 75\" xmlns=\"http://www.w3.org/2000/svg\"><rect width=\"75\" height=\"75\" fill=\"#FF6B35\"/><text   x=\"37.   5\" y=\"45\" font-family=\"Arial\" font-size=\"18\" fill=\"white\" text-anchor=\"middle\" font-weight=\"bold\">CONTOSO</text></svg>",
           "Description": "The Contoso Security Alerts solution provides real-time security alert ingestion from your Contoso application into Microsoft Sentinel using the       Codeless Connector Framework (CCF) Push pattern. Your application pushes alert severity, event types, user information, and network details directly to Azure   Monitor     for analysis, alerting, and visualization.",
           "Data Connectors": [
                "Data Connectors/ContosoSecurityAlerts_ccf/connectorDefinition.json"
           ],
           "BasePath": "C:\\GitHub\\Azure-Sentinel\\Solutions\\ContosoSecurityAlerts",
           "Version": "1.0.0",
           "Metadata": "SolutionMetadata.json",
           "TemplateSpec": true,
           "Is1PConnector": false
      }
      

      중요합니다

      중요한 필드 요구 사항:

      • BasePath: Azure-Sentinel 리포지토리의 실제 로컬 경로로 업데이트
      • Metadata: SolutionMetadata.json를 반드시 참조해야 합니다(6B단계에서 생성됨)
      • Version: 의미 체계 버전 관리(예: 3.0.0
      • TemplateSpec: 항상 true 콘텐츠 허브 솔루션
      • Is1Pconnector: 파트너/사용자 지정 커넥터에 대해 false으로 설정
    2. 솔루션 루트에서 SolutionMetadata.json 만들기

      ContosoSecurityAlerts 폴더의 솔루션 루트 디렉터리(데이터 폴더와 동일한 수준)에서 SolutionMetadata.json 만듭니다.

      {
        "publisherId": "contoso",
        "offerId": "contoso-security-alerts",
        "firstPublishDate": "2025-01-01",
        "lastPublishDate": "2025-01-01",
        "providers": [
           "Contoso"
        ],
        "categories": {
           "domains": [
              "Security - Threat Protection",
              "Security - Cloud Security"
           ]
        },
        "support": {
           "name": "Contoso Corporation",
           "tier": "Partner",
           "link": "https://www.contoso.com/support"
        }
      }
      

      Content Hub 패키징을 위한 SolutionMetadata.json 파일이 필요합니다.

      • 패키징 도구는 솔루션 루트에서 이 파일을 예상합니다.
      • 콘텐츠 허브 배포에 대한 마켓플레이스 메타데이터가 포함되어 있습니다.
    3. 솔루션 루트에서 ReleaseNotes.md 만들기

      버전 수정된 날짜(DD-MM-YYYY) 변경 기록
      3.0.0 DD-MM-YYYY 예제 솔루션

    유효성 검사 목록

    다음 단계를 진행하기 전에 다음을 확인합니다.

    • 예를 들어 폴더 이름에는 공백이 없습니다. ContosoSecurityAlerts
    • Name Solution_ContosoSecurityAlerts.json 필드가 폴더 이름과 정확히 일치합니다.
    • SolutionMetadata.json 솔루션 루트에 있음(데이터 폴더에 없음)
    • BasePath 실제 로컬 Azure-Sentinel 리포지토리 경로를 가리킵니다.
    • Metadata 필드는 "SolutionMetadata.json"을 참조합니다.
    • publisherIdofferId 두 파일 간의 일치
  8. 솔루션 구조 확인

    폴더 구조가 모든 파일이 있는 필수 레이아웃과 일치하는지 확인합니다.

    Azure-Sentinel/
    └── Solutions/
         └── ContosoSecurityAlerts/                         Folder name (no spaces)
              ├── Data/
              │   └── Solution_ContosoSecurityAlerts.json    From Step 7A
              ├── SolutionMetadata.json                      From Step 7B (at root)
              ├── ReleaseNotes.md                            From Step 7C
              └── Data Connectors/
                    └── ContosoSecurityAlerts_ccf/
                         ├── table.json                         From Step 3
                         ├── DCR.json                           From Step 4
                         ├── connectorDefinition.json           From Step 5
                         └── dataConnector.json                 From Step 6
    
  9. 솔루션 패키지

    createSolutionV3.ps1 패키징 도구를 사용하여 ARM 배포 템플릿을 생성합니다.

    # Navigate to the packaging tools directory (from Azure-Sentinel repository root)
    cd Tools/Create-Azure-Sentinel-Solution/V3
    
    # Run the packaging tool
    # When prompted for "Enter solution data folder path:", provide:
    # <REPO_ROOT>Solutions/ContosoSecurityAlerts/Data (Note! This path is absolute)
    .\createSolutionV3.ps1
    

    스크립트는 자동으로 다음을 수행합니다.

    • 데이터/폴더 구조의 유효성을 검사합니다.
    • 커넥터 아티팩트 처리

    예상 출력:

    패키징 스크립트는 실패한 arm-ttk(Azure Resource Manager 템플릿 도구 키트) 유효성 검사를 보여 줍니다. CCF 푸시 커넥터의 경우 이 오류가 예상되고 정상입니다.

    Failed arm-ttk (Test-AzTemplate): Package
    Failed arm-ttk (Test-AzTemplate) on solutions: Package
    ************Validating if Package Json files are valid or not***************
    File Solutions\ContosoSecurityAlerts\Package\createUiDefinition.json is a valid Json file!
    File Solutions\ContosoSecurityAlerts\Package\mainTemplate.json is a valid Json file!
    File Solutions\ContosoSecurityAlerts\Package\testParameters.json is a valid Json file!
    

    유효한 파일을 확인하는 세 개의 JSON 유효성 검사 메시지가 표시되면 패키징에 성공했습니다. CCF 푸시 커넥터의 arm-ttk 실패를 무시할 수 있습니다.

    자세한 내용은 Azure-Sentinel 솔루션 도구 설명서를 참조하세요.

  10. 솔루션 패키지 배포

    생성된 ARM 템플릿(패키지/mainTemplate.json)을 Azure 구독에 배포합니다.

    1. Azure Portal에서 사용자 지정 템플릿 배포를 검색합니다.
    2. 편집기에서 고유한 템플릿 빌드 선택
    3. 파일 로드를 선택하고 출력 폴더에서 선택 Package/mainTemplate.json
    4. 저장을 선택합니다.
    5. 배포 매개 변수를 입력합니다.
      • 구독: Azure 구독
      • 리소스 그룹: Sentinel 작업 영역이 포함된 리소스 그룹
      • 지역: Sentinel 작업 영역과 동일한 지역
      • 작업 영역: Log Analytics 작업 영역 이름
    6. 검토 + 만들기를 선택한 다음 만들기

    이 배포를 통해 Microsoft Sentinel 데이터 커넥터 갤러리에서 커넥터를 사용할 수 있습니다.

    자세한 단계는 [빠른 시작: Azure Portal을 사용하여 ARM 템플릿 만들기 및 배포](/azure/azure-resource-manager/templates/ quickstart-create-templates-use-the-Portal)를 참조하세요.

  11. 데이터 커넥터 사용

    솔루션 패키지를 배포한 후 커넥터가 리소스를 프로비전하고 자격 증명을 생성하도록 설정합니다.

    1. Azure Portal에서 Microsoft Sentinel 작업 영역으로 이동합니다.
    2. 구성>데이터 커넥터로 이동
    3. Contoso 보안 경고 검색 및 선택(푸시)
    4. 커넥터 열기 페이지 선택
    5. Contoso 보안 경고 배포 커넥터 단추 선택
    6. 배포가 완료되기를 기다립니다(자격 증명을 사용하여 사용자 지정 테이블, DCR, DCE, Entra 애플리케이션 만들기)
    7. 표시되는 연결 세부 정보를 복사합니다.
      • 임차인 ID
      • 애플리케이션(클라이언트) ID
      • 클라이언트 암호
      • 데이터 수집 엔드포인트 URI
      • 데이터 수집 규칙 변경할 수 없는 ID
      • 스트림 이름: Custom-ContosoSecurityAlerts
  12. 애플리케이션 구성

    10단계의 자격 증명 및 리소스 세부 정보로 애플리케이션 코드를 업데이트합니다. 이 코드는 OAuth 2.0 클라이언트 자격 증명 흐름을 사용하여 Azure Monitor로 인증합니다.

    주의

    자격 증명 보호: 애플리케이션 코드에서 직접 자격 증명(테넌트 ID, 애플리케이션 ID, 클라이언트 암호)을 하드 코딩하거나 소스 제어에 커밋하지 않습니다. 다음과 같은 보안 자격 증명 스토리지 솔루션을 사용합니다.

    • 프로덕션 애플리케이션용 Azure Key Vault
    • 환경 변수 또는 구성 파일(소스 제어에서 제외)
    • 적용 가능한 경우 관리형 ID 사용
    • 휴지 상태의 자격 증명을 암호화하는 비밀 관리 도구

    Python 예제 애플리케이션 코드:

    다음 예제에서는 Your-Tenant-ID<와 같은 >자리 표시자 값을 사용합니다. 이러한 값을 실제 자격 증명에 대한 보안 참조로 대체합니다.

    import requests
    import json
    from datetime import datetime, timezone
    
    # Connection details from Step 11
    
    tenant_id = "<Your-Tenant-ID>"
    app_id = "<Your-Application-ID>"
    app_secret = "<Your-Client-Secret>"
    dce_uri = "<Your-DCE-URI>"
    dcr_immutable_id = "<Your-DCR-Immutable-ID>"
    stream_name = "Custom-ContosoSecurityAlerts"
    
    
    **Get OAuth token**
    
    token_url = f"https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token"
    token_data = {
         "client_id": app_id,
         "scope": "https://monitor.azure.com//.default",
         "client_secret": app_secret,
         "grant_type": "client_credentials"
    }
    token_response = requests.post(token_url, data=token_data)
    access_token = token_response.json()["access_token"]
    
    
    # Create event matching your table schema
    
    event = [{
         "TimeGenerated": datetime.now(timezone.utc).isoformat(),
         "EventSeverity": "Medium",
         "EventType": "LoginAlert",
         "UserName": "alice@contoso.com",
         "SourceIP": "192.168.1.100",
         "DeviceId": "device-12345",
         "AlertMessage": "Multiple failed login attempts detected"
    }]
    
    
    # Send to Sentinel
    
    headers = {
         "Authorization": f"Bearer {access_token}",
         "Content-Type": "application/json"
    }
    upload_url = f"{dce_uri}/dataCollectionRules/{dcr_immutable_id}/streams/{stream_name}?api-version=2023-01-01"
    response = requests.post(upload_url, headers=headers, json=event)
    
    print(f"Status: {response.status_code}")
    print("Security alert sent to Sentinel!")
    
  13. 데이터 쿼리

    경고를 보낸 후 Sentinel에서 쿼리합니다. 첫 번째 수집에는 5~10분 정도 걸릴 수 있습니다.

    // View all recent alerts
    ContosoSecurityAlerts_CL
    | where TimeGenerated > ago(1h)
    | order by TimeGenerated desc
    
    // High severity alerts
    ContosoSecurityAlerts_CL
    | where EventSeverity == "High"
    | project TimeGenerated, EventType, UserName, SourceIP, AlertMessage
    
    // Alert summary by severity
    ContosoSecurityAlerts_CL
    | where TimeGenerated > ago(7d)
    | summarize Count=count() by EventSeverity
    

이제 CCF 푸시 커넥터를 이해했으므로 다음 단계를 수행합니다.

  1. 데이터 스키마 디자인 - 보내려는 이벤트와 해당 필드를 식별합니다.
  2. 커넥터 아티팩트 만들기 - 4개의 JSON 파일(테이블, DCR, 커넥터 정의, 데이터 커넥터)을 빌드합니다.
  3. 솔루션 구조 구성 - 적절한 이름을 사용하여 데이터/및 데이터 커넥터/폴더를 설정합니다.
  4. 솔루션 패키지 - 배포 템플릿을 생성하는 데 사용합니다 createSolutionV3.ps1 .
  5. 배포 및 테스트 - Sentinel 작업 영역에 배포하고 데이터 흐름의 유효성을 검사합니다.
  6. 애플리케이션과 통합 - 실시간으로 이벤트를 보내는 코드를 추가합니다.
  7. 경고 및 통합 문서 만들기 - 보안 모니터링에 데이터를 사용합니다.

추가 리소스

CCF 설명서

Azure Monitor 및 데이터 수집

인증 및 보안

Microsoft Sentinel

도움받기

  • 통합을 구축하는 ISV 파트너의 경우 다음을 문의하세요. azuresentinelpartner@microsoft.com
  • 기술 질문은 'azure-sentinel' 태그와 함께 Microsoft Q&A 를 사용합니다.