{
    "id": "DuoSecurity",
    "title": "Duo Security",
    "publisher": "Duo",
    "descriptionMarkdown": "The [Duo Security](https://duo.com/) data connector provides the capability to ingest log data into Azure Sentinel through the Duo Security Admin API. The connector provides visibility into activity logs from the service. This connector provides Azure Sentinel the capability to view dashboards, create custom alerts, and improve investigation ",
    "graphQueries": [
        {
            "metricName": "Total data received",
            "legend": "DuoSecurityAdministrator_CL",
            "baseQuery": "DuoSecurityAdministrator_CL"
        },
        {
            "metricName": "Total data received",
            "legend": "DuoSecurityAuthentication_CL",
            "baseQuery": "DuoSecurityAuthentication_CL"
        },
        {
            "metricName": "Total data received",
            "legend": "DuoSecurityOfflineEnrollment_CL",
            "baseQuery": "DuoSecurityOfflineEnrollment_CL"
        },
        {
            "metricName": "Total data received",
            "legend": "DuoSecurityTelephony_CL",
            "baseQuery": "DuoSecurityTelephony_CL"
        },
        {
            "metricName": "Total data received",
            "legend": "DuoSecurityTrustMonitor_CL",
            "baseQuery": "DuoSecurityTrustMonitor_CL"
        }
    ],
    "sampleQueries": [
        {
            "description" : "Top 10 Administrator Actions",
            "query": "DuoSecurityAdministrator_CL\n |  summarize count() by action_s\n | top 10 by count_"
        },
        {
            "description" : "Top 10 Users Authentications",
            "query": "DuoSecurityAuthentication_CL\n |  summarize count() by email_s\n | top 10 by count_"
        },
        {
            "description" : "Last 10 Offline Enrollments",
            "query": "DuoSecurityOfflineEnrollment_CL\n |  sort by isotimestamp_t desc\n | top 10 by isotimestamp_t"
        },
        {
            "description" : "Top 10 Telephones Dialed",
            "query": "DuoSecurityTelephony_CL\n |  summarize count() by phone_s\n | top 10 by count_"
        },
        {
            "description" : "Last 10 Trust Monitor Events",
            "query": "let fromUnixTime = (t:long){datetime(1970-01-01) + t * 1sec};\n DuoSecurityTrustMonitor_CL\n | extend surfaceTime = fromUnixTime(surfaced_timestamp_d)\n | sort by surfaceTime desc\n | top 10 by surfaceTime"
        }
     ],
    "dataTypes": [
        {
            "name": "DuoSecurityAdministrator_CL",
            "lastDataReceivedQuery": "DuoSecurityAdministrator_CL\n            | summarize Time = max(TimeGenerated)\n            | where isnotempty(Time)"
        },
        {
            "name": "DuoSecurityAuthentication_CL",
            "lastDataReceivedQuery": "DuoSecurityAuthentication_CL\n            | summarize Time = max(TimeGenerated)\n            | where isnotempty(Time)"
        },
        {
            "name": "DuoSecurityOfflineEnrollment_CL",
            "lastDataReceivedQuery": "DuoSecurityOfflineEnrollment_CL\n            | summarize Time = max(TimeGenerated)\n            | where isnotempty(Time)"
        },
        {
            "name": "DuoSecurityTelephony_CL",
            "lastDataReceivedQuery": "DuoSecurityTelephony_CL\n            | summarize Time = max(TimeGenerated)\n            | where isnotempty(Time)"
        },
        {
            "name": "DuoSecurityTrustMonitor_CL",
            "lastDataReceivedQuery": "DuoSecurityTrustMonitor_CL\n            | summarize Time = max(TimeGenerated)\n            | where isnotempty(Time)"
        }
    ],
    "connectivityCriterias": [
        {
            "type": "IsConnectedQuery",
            "value": [
                "DuoSecurityAdministrator_CL\n            | summarize LastLogReceived = max(TimeGenerated)\n            | project IsConnected = LastLogReceived > ago(30d)",
                "DuoSecurityAuthentication_CL\n            | summarize LastLogReceived = max(TimeGenerated)\n            | project IsConnected = LastLogReceived > ago(30d)",
                "DuoSecurityOfflineEnrollment_CL\n            | summarize LastLogReceived = max(TimeGenerated)\n            | project IsConnected = LastLogReceived > ago(30d)",
                "DuoSecurityTelephony_CL\n            | summarize LastLogReceived = max(TimeGenerated)\n            | project IsConnected = LastLogReceived > ago(30d)",
                "DuoSecurityTrustMonitor_CL\n            | summarize LastLogReceived = max(TimeGenerated)\n            | project IsConnected = LastLogReceived > ago(30d)"
            ]
        }
    ],
    "availability": {
        "status": 1,
        "isPreview": true
    },
    "permissions": {
        "resourceProvider": [
            {
                "provider": "Microsoft.OperationalInsights/workspaces",
                "permissionsDisplayText": "read and write permissions on the workspace are required.",
                "providerDisplayName": "Workspace",
                "scope": "Workspace",
                "requiredPermissions": {
                    "write": true,
                    "read": true,
                    "delete": true
                }
            },
            {
                "provider": "Microsoft.OperationalInsights/workspaces/sharedKeys",
                "permissionsDisplayText": "read permissions to shared keys for the workspace are required. [See the documentation to learn more about workspace keys](https://docs.microsoft.com/azure/azure-monitor/platform/agent-windows#obtain-workspace-id-and-key).",
                "providerDisplayName": "Keys",
                "scope": "Workspace",
                "requiredPermissions": {
                    "action": true
                }
            }
        ],
        "customs": [
            {
                "name": "Microsoft.Web/sites permissions",
                "description": "Read and write permissions to Azure Functions to create a Function App is required. [See the documentation to learn more about Azure Functions](https://docs.microsoft.com/azure/azure-functions/)."
            },
            {
                "name": "Duo Security Admin API",
                "description": "A Duo Security Admin API Integration Key, Secret Key and API Hostname is required. [See the documentation to learn more about Duo Security Admin API](https://duo.com/docs/adminapi)."
            }
        ]
    },
    "instructionSteps": [
        {
            "title": "",
            "description": ">**NOTE:** This connector uses Azure Functions to connect to Duo Security to pull its logs into Azure Sentinel. This might result in additional data ingestion costs. Check the [Azure Functions pricing page](https://azure.microsoft.com/pricing/details/functions/) for details."
        },
        {
            "title": "",
            "description": ">**(Optional Step)** Securely store workspace and API authorization key(s) or token(s) in Azure Key Vault. Azure Key Vault provides a secure mechanism to store and retrieve key values. [Follow these instructions](https://docs.microsoft.com/azure/app-service/app-service-key-vault-references) to use Azure Key Vault with an Azure Function App."
        },
        {
            "title": "",
            "description": "**STEP 1 - Configuration steps for the Duo Security Admin API**\n\n1. Log into the Duo Admin Panel with an administrator account, select **Application**. \n2. Click on the **Protect an Application** button and locate the entry for **Admin API**.  Click **Protect** \n3. Copy you **integration key**, **secret key** and **api hostname**. \n4. Check the box to **Grat read log** permissions." 
        },
        {
            "title": "",
            "description": "**STEP 2 - Choose ONE from the following two deployment options to deploy the connector and the associated Azure Function**\n\n>**IMPORTANT:** Before deploying the Duo Security connector, have the Workspace ID and Workspace Primary Key (can be copied from the following), as well as the Duo Security integration key, secret key and api host, readily available.", 
            "instructions":[
                {
                    "parameters": {
                        "fillWith": [
                            "WorkspaceId"
                        ],
                        "label": "Workspace ID"
                    },
                    "type": "CopyableLabel"
                },
                {
                    "parameters": {
                        "fillWith": [
                            "PrimaryKey"
                        ],
                        "label": "Primary Key"
                    },
                    "type": "CopyableLabel"
                }
            ]
        },
        {
            "title": "Option 1 - Azure Resource Manager (ARM) Template",
            "description": "Use this method for automated deployment of the Duo Security connector using an ARM Tempate.\n\n1. Click the **Deploy to Azure** button below. \n\n\t[![Deploy To Azure](https://aka.ms/sentinel-duosecurity-azuredeploy)](https://aka.ms/sentinelduosecurityazuredeploy)\n2. Select the preferred **Subscription**, **Resource Group** and **Location**. \n3. Enter the **Workspace ID**, **Workspace Key**, **Integration Key**, **Secret Key** , and **API Host**. \n - The default **Time Interval** is set to pull the last five (5) minutes of data. If the time interval needs to be modified, it is recommended to change the Function App Environment varibles **Schedule** and **timeInterval**. \n> - Note: If using Azure Key Vault secrets for any of the values above, use the`@Microsoft.KeyVault(SecretUri={Security Identifier})`schema in place of the string values. Refer to [Key Vault references documentation](https://docs.microsoft.com/azure/app-service/app-service-key-vault-references) for further details. \n4. Mark the checkbox labeled **I agree to the terms and conditions stated above**. \n5. Click **Purchase** to deploy."
        },
        {
            "title": "Option 2 - Manual Deployment of Azure Functions",
            "description": "Use the following step-by-step instructions to deploy the Duo Security connector manually with Azure Functions."
        },
        {
            "title": "",
            "description": "**1. Create a Function App**\n\n1.  From the Azure Portal, navigate to [Function App](https://portal.azure.com/#blade/HubsExtension/BrowseResource/resourceType/Microsoft.Web%2Fsites/kind/functionapp), and select **+ Add**.\n2. In the **Basics** tab, ensure Runtime stack is set to **Powershell Core**. \n3. In the **Hosting** tab, ensure the **Consumption (Serverless)** plan type is selected.\n4. Make other preferrable configuration changes, if needed, then click **Create**."
        },
        {
            "title": "",
            "description": "**2. Import Function App Code**\n\n1. In the newly created Function App, select **Functions** on the left pane and click **+ New Function**.\n2. Select **Timer Trigger**.\n3. Enter a unique Function **Name** and leave the default cron schedule of every 5 minutes, then click **Create**.\n5. Click on **Code + Test** on the left pane. \n6. Copy the [Function App Code](https://aka.ms/sentinel-duosecurity-functioncode) and paste into the Function App `run.ps1` editor.\n7. Click **Save**."
        },
        {
            "title": "",
            "description": "**3. Configure the Function App**\n\n1. In the Function App, select the Function App Name and select **Configuration**.\n2. In the **Application settings** tab, select **+ New application setting**.\n3. Add each of the following seven (6) application settings individually, with their respective string values (case-sensitive): \n\t\tiKey\n\t\tsKey\n\t\tapiServer\n\t\ttimeInterval\n\t\ttimeInterval\n\t\tworkspaceID\n\t\tworkspaceKey\n> - The `apiServer` value must follow the following schema: `api-<something>.duosecurity.com`.\n> - Set the `timeInterval` (in minutes) to the value of `5` to correspond to the Timer Trigger of every `5` minutes. If the time interval needs to be modified, it is recommended to change the Function App Timer Trigger accordingly to prevent overlapping data ingestion.\n> - Note: If using Azure Key Vault, use the`@Microsoft.KeyVault(SecretUri={Security Identifier})`schema in place of the string values. Refer to [Key Vault references documentation](https://docs.microsoft.com/azure/app-service/app-service-key-vault-references) for further details.\n4. Once all application settings have been entered, click **Save**."
        }
    ],
    "metadata": {
        "id": "4f20e938-1c6d-474d-b7b3-fdd2e4d15435",
        "version": "1.0.0",
        "kind": "dataConnector",
        "source": {
            "kind": "community",
            "name": "Name of the content source. The repo name, solution name, LA workspace name etc."
        },
        "author": {
            "name": "Nicholas DiCola"
        },
        "support": {
            "tier": "community",
            "name": "GitHub Issues",
            "email": "",
            "link":"https://github.com/Azure/Azure-Sentinel/issues"
        }
    }
}
