{
  "name": "TailscalePremiumCCF",
  "apiVersion": "2022-09-01-preview",
  "type": "Microsoft.SecurityInsights/dataConnectorDefinitions",
  "kind": "Customizable",
  "properties": {
    "connectorUiConfig": {
      "title": "Tailscale Premium (CCF)",
      "publisher": "Community",
      "logo": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbDpzcGFjZT0icHJlc2VydmUiIGlkPSJMYXllcl8xIiB4PSIwIiB5PSIwIiB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCA1MTIgNTEyIj48c3R5bGU+LnN0MHtvcGFjaXR5Oi4yO2VuYWJsZS1iYWNrZ3JvdW5kOm5ld308L3N0eWxlPjxwYXRoIGQ9Ik02NS42IDEyNy43YzM1LjMgMCA2My45LTI4LjYgNjMuOS02My45UzEwMC45IDAgNjUuNiAwIDEuOCAyOC42IDEuOCA2My45czI4LjYgNjMuOCA2My44IDYzLjgiIGNsYXNzPSJzdDAiLz48cGF0aCBkPSJNNjUuNiAzMTguMWMzNS4zIDAgNjMuOS0yOC42IDYzLjktNjMuOXMtMjguNi02My45LTYzLjktNjMuOVMxLjggMjE5IDEuOCAyNTQuMnMyOC42IDYzLjkgNjMuOCA2My45Ii8+PHBhdGggZD0iTTY1LjYgNTEyYzM1LjMgMCA2My45LTI4LjYgNjMuOS02My45cy0yOC42LTYzLjktNjMuOS02My45LTYzLjggMjguNy02My44IDYzLjlTMzAuNCA1MTIgNjUuNiA1MTIiIGNsYXNzPSJzdDAiLz48cGF0aCBkPSJNMjU3LjIgMzE4LjFjMzUuMyAwIDYzLjktMjguNiA2My45LTYzLjlzLTI4LjYtNjMuOS02My45LTYzLjktNjMuOSAyOC42LTYzLjkgNjMuOSAyOC42IDYzLjkgNjMuOSA2My45bTAgMTkzLjljMzUuMyAwIDYzLjktMjguNiA2My45LTYzLjlzLTI4LjYtNjMuOS02My45LTYzLjktNjMuOSAyOC42LTYzLjkgNjMuOSAyOC42IDYzLjkgNjMuOSA2My45Ii8+PHBhdGggZD0iTTI1Ny4yIDEyNy43YzM1LjMgMCA2My45LTI4LjYgNjMuOS02My45UzI5Mi41IDAgMjU3LjIgMHMtNjMuOSAyOC42LTYzLjkgNjMuOSAyOC42IDYzLjggNjMuOSA2My44bTE4OS4yIDBjMzUuMyAwIDYzLjktMjguNiA2My45LTYzLjlTNDgxLjYgMCA0NDYuNCAwYy0zNS4zIDAtNjMuOSAyOC42LTYzLjkgNjMuOXMyOC42IDYzLjggNjMuOSA2My44IiBjbGFzcz0ic3QwIi8+PHBhdGggZD0iTTQ0Ni40IDMxOC4xYzM1LjMgMCA2My45LTI4LjYgNjMuOS02My45cy0yOC42LTYzLjktNjMuOS02My45LTYzLjkgMjguNi02My45IDYzLjkgMjguNiA2My45IDYzLjkgNjMuOSIvPjxwYXRoIGQ9Ik00NDYuNCA1MTJjMzUuMyAwIDYzLjktMjguNiA2My45LTYzLjlzLTI4LjYtNjMuOS02My45LTYzLjktNjMuOSAyOC42LTYzLjkgNjMuOSAyOC42IDYzLjkgNjMuOSA2My45IiBjbGFzcz0ic3QwIi8+PC9zdmc+",
      "descriptionMarkdown": "Comprehensive Tailscale telemetry for **Premium and Enterprise** tier tailnets. Polls every endpoint the Standard connector polls, **plus** Premium-only network flow logs and posture-integration inventory. Eleven endpoints in one Connect:\n\n- `/logging/configuration` - configuration audit events\n- `/logging/network` - **Premium** network flow logs (per-node traffic with src/dst/protocol/bytes)\n- `/devices` - device inventory\n- `/users` - user inventory\n- `/keys?all=true` - auth keys + API tokens + OAuth clients\n- `/webhooks` - webhook configuration\n- `/dns/nameservers`, `/dns/preferences`, `/dns/searchpaths` - DNS state (merged into single `Tailscale_Dns_CL` table with `ConfigType` discriminator)\n- `/settings` - tailnet settings flags\n- `/posture/integrations` - **Premium** MDM/EDR integration inventory (Jamf, Kandji, Intune, Kolide, Microsoft Defender for Endpoint, CrowdStrike Falcon, SentinelOne, etc.)\n\n**OAuth scopes required:** `logs:configuration:read`, `logs:network:read`, `devices:core:read`, `users:read`, `auth_keys:read`, `webhooks:read`, `dns:read`, `feature_settings:read` (or the bundled `all:read`).\n\n**If your tailnet is Personal (Free) or Standard tier, install `Tailscale Standard (CCF)` instead - this Premium connector's network and posture pollers will return 403 on lower tiers.**",
      "graphQueries": [
        {
          "metricName": "Audit",
          "legend": "Tailscale_Audit_CL",
          "baseQuery": "Tailscale_Audit_CL"
        },
        {
          "metricName": "Devices",
          "legend": "Tailscale_Devices_CL",
          "baseQuery": "Tailscale_Devices_CL"
        },
        {
          "metricName": "Users",
          "legend": "Tailscale_Users_CL",
          "baseQuery": "Tailscale_Users_CL"
        },
        {
          "metricName": "Keys",
          "legend": "Tailscale_Keys_CL",
          "baseQuery": "Tailscale_Keys_CL"
        },
        {
          "metricName": "Webhooks",
          "legend": "Tailscale_Webhooks_CL",
          "baseQuery": "Tailscale_Webhooks_CL"
        },
        {
          "metricName": "Settings",
          "legend": "Tailscale_Settings_CL",
          "baseQuery": "Tailscale_Settings_CL"
        },
        {
          "metricName": "Network",
          "legend": "Tailscale_Network_CL",
          "baseQuery": "Tailscale_Network_CL"
        },
        {
          "metricName": "PostureIntegrations",
          "legend": "Tailscale_PostureIntegrations_CL",
          "baseQuery": "Tailscale_PostureIntegrations_CL"
        },
        {
          "metricName": "DNS config snapshots",
          "legend": "Tailscale_Dns_CL",
          "baseQuery": "Tailscale_Dns_CL"
        }
      ],
      "dataTypes": [
        {
          "name": "Tailscale_Audit_CL",
          "lastDataReceivedQuery": "[format('{0} | summarize Time=max(TimeGenerated)', 'Tailscale_Audit_CL')]"
        },
        {
          "name": "Tailscale_Devices_CL",
          "lastDataReceivedQuery": "[format('{0} | summarize Time=max(TimeGenerated)', 'Tailscale_Devices_CL')]"
        },
        {
          "name": "Tailscale_Users_CL",
          "lastDataReceivedQuery": "[format('{0} | summarize Time=max(TimeGenerated)', 'Tailscale_Users_CL')]"
        },
        {
          "name": "Tailscale_Keys_CL",
          "lastDataReceivedQuery": "[format('{0} | summarize Time=max(TimeGenerated)', 'Tailscale_Keys_CL')]"
        },
        {
          "name": "Tailscale_Webhooks_CL",
          "lastDataReceivedQuery": "[format('{0} | summarize Time=max(TimeGenerated)', 'Tailscale_Webhooks_CL')]"
        },
        {
          "name": "Tailscale_Settings_CL",
          "lastDataReceivedQuery": "[format('{0} | summarize Time=max(TimeGenerated)', 'Tailscale_Settings_CL')]"
        },
        {
          "name": "Tailscale_Network_CL",
          "lastDataReceivedQuery": "[format('{0} | summarize Time=max(TimeGenerated)', 'Tailscale_Network_CL')]"
        },
        {
          "name": "Tailscale_PostureIntegrations_CL",
          "lastDataReceivedQuery": "[format('{0} | summarize Time=max(TimeGenerated)', 'Tailscale_PostureIntegrations_CL')]"
        },
        {
          "name": "Tailscale_Dns_CL",
          "lastDataReceivedQuery": "[format('{0} | summarize Time=max(TimeGenerated)', 'Tailscale_Dns_CL')]"
        }
      ],
      "sampleQueries": [
        {
          "description": "Recent network flows",
          "query": "Tailscale_Network_CL\n| sort by TimeGenerated desc\n| take 100"
        },
        {
          "description": "Top exit-node egress destinations",
          "query": "Tailscale_Network_CL\n| where array_length(ExitTraffic) > 0\n| mv-expand t = ExitTraffic\n| extend Bytes = tolong(t.txBytes) + tolong(t.rxBytes), ExitDst = tostring(t.dst)\n| summarize TotalBytes = sum(Bytes) by ExitDst\n| top 25 by TotalBytes"
        },
        {
          "description": "Currently configured posture integrations",
          "query": "Tailscale_PostureIntegrations_CL\n| summarize arg_max(TimeGenerated, *) by IntegrationId\n| project IntegrationId, Provider, ClientId, Status"
        },
        {
          "description": "Device inventory by OS",
          "query": "Tailscale_Devices_CL\n| summarize arg_max(TimeGenerated, *) by DeviceId\n| summarize Devices = count() by Os"
        },
        {
          "description": "Recent audit events",
          "query": "Tailscale_Audit_CL\n| sort by TimeGenerated desc\n| take 100"
        },
        {
          "description": "Current DNS state (all DNS config in one query)",
          "query": "Tailscale_Dns_CL\n| summarize arg_max(TimeGenerated, *) by ConfigType\n| project ConfigType, Nameservers, MagicDNS, SearchPaths"
        }
      ],
      "connectivityCriteria": [
        {
          "type": "HasDataConnectors"
        }
      ],
      "availability": {
        "status": 1,
        "isPreview": true
      },
      "permissions": {
        "resourceProvider": [
          {
            "provider": "Microsoft.OperationalInsights/workspaces",
            "permissionsDisplayText": "Read/Write on the workspace",
            "providerDisplayName": "Workspace",
            "scope": "Workspace",
            "requiredPermissions": {
              "write": true,
              "read": true,
              "delete": true
            }
          }
        ]
      },
      "instructionSteps": [
        {
          "title": "Connect Tailscale (Premium)",
          "description": "Generate an OAuth client at https://login.tailscale.com/admin/settings/oauth with these **Read** scopes: Logs > Configuration, Logs > Network (Premium), General > DNS, General > Users, Devices > Core, Keys > Auth Keys, Keys > Webhooks, Settings > Feature Settings (or tick `all:read`). Find your tailnet name on the Keys page.",
          "instructions": [
            {
              "type": "Textbox",
              "parameters": {
                "label": "Tailscale tailnet",
                "placeholder": "tail-XXXX.ts.net",
                "type": "text",
                "name": "tailnetName"
              }
            },
            {
              "type": "Textbox",
              "parameters": {
                "label": "OAuth Client ID",
                "placeholder": "k...",
                "type": "text",
                "name": "clientId"
              }
            },
            {
              "type": "Textbox",
              "parameters": {
                "label": "OAuth Client Secret",
                "placeholder": "tskey-client-...",
                "type": "password",
                "name": "clientSecret"
              }
            },
            {
              "type": "ConnectionToggleButton",
              "parameters": {
                "connectLabel": "Connect",
                "disconnectLabel": "Disconnect"
              }
            }
          ]
        }
      ],
      "id": "TailscalePremiumCCF"
    }
  }
}