ACN_CD_Netskope_DataConnector01 (#1313)

* Netskope Connector

* revisions

* revisions 2

* updated filename
This commit is contained in:
chicduong 2020-11-24 14:29:06 -08:00 коммит произвёл GitHub
Родитель cb19dc7e74
Коммит d104b3816b
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
9 изменённых файлов: 14821 добавлений и 0 удалений

Двоичные данные
DataConnectors/Netskope/AzureFunctionNetskope.zip Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,11 @@
{
"bindings": [
{
"type": "timerTrigger",
"name": "Timer",
"schedule": "0 */5 * * * *",
"direction": "in"
}
],
"disabled": false
}

Просмотреть файл

@ -0,0 +1,203 @@
<#
Title: Netskope Connector
Language: PowerShell
Version: 1.0
Author(s): Microsoft
Last Modified: 11/13/2020
Comment: Initial Release
DESCRIPTION
This Function App calls the Netskope Platform API (https://innovatechcloud.goskope.com/docs/Netskope_Help/en/rest-api-v2-overview.html) to pull alert and events data. The response from the Netskope API is recieved in JSON format. This function will build the signature and authorization header
needed to post the data to the Log Analytics workspace via the HTTP Data Connector API. The Function App will post to the Netskope_CL table in the Log Analytics workspace.
#>
# Input bindings are passed in via param block.
param($Timer)
# Get the current universal time in the default string format.
$currentUTCtime = (Get-Date).ToUniversalTime()
# The 'IsPastDue' property is 'true' when the current function invocation is later than scheduled.
if ($Timer.IsPastDue) {
Write-Host "PowerShell timer is running late!"
}
# Function to contruct the Netskope Uri for alerts, event types, and to accomodate for pagination
function GetUrl ($uri, $ApiKey, $StartTime, $EndTime, $LogType, $Page, $Skip){
if("$logtype" -eq "alert") {
$url = "$uri/api/v1/alerts?token=$ApiKey&limit=$Page&starttime=$StartTime&endtime=$EndTime"
}
else{
$url = "$uri/api/v1/events?token=$ApiKey&limit=$Page&type=$LogType&starttime=$StartTime&endtime=$EndTime"
}
if($skip -ne 0){
$url = "$url&skip=$Skip"
Write-Host "Retrieving next page of $LogType events skipping the previous $Skip records"
return $url
}
else{
return $url
}
}
# Function for retrieving alerts and events from Netskope's APIs
function GetLogs ($Uri, $ApiKey, $StartTime, $EndTime, $LogType, $Page, $Skip){
$url = GetUrl -Uri $Uri -ApiKey $ApiKey -StartTime $StartTime -EndTime $EndTime -logtype $LogType -Page $Page -Skip $Skip
$obfurl = $url -replace "token=[a-z0-9]+\&", "token=<apiToken>&"
Write-Host "Retrieving '$LogType' events from $obfurl"
$response = Invoke-RestMethod -Uri $url
if ($response.status -eq "error") {
$errorCode = $response.errorCode
$errors = $response.errors
Write-Host "ERROR encountered while retrieving '$LogType' events - $errorCode - $errors"
}
else {
return $response
}
}
# Function to retrieve the checkpoint start time of the last successful API call for a given logtype. Checkpoint file will be created if none exists
function GetStartTime($CheckpointFile, $LogType, $TimeInterval){
$firstEndTimeRecord = (Get-Date -Date ((Get-Date).DateTime) -UFormat %s)
$firstStartTimeRecord = $firstEndTimeRecord - $TimeInterval
if ([System.IO.File]::Exists($CheckpointFile) -eq $false) {
$CheckpointLog = @{}
foreach ($apiType in $apitypes){
$CheckpointLog.Add($apiType,$firstStartTimeRecord)
}
$CheckpointLog.GetEnumerator() | Select-Object -Property Key,Value | Export-CSV -Path $CheckpointFile -NoTypeInformation
return $firstStartTimeRecord
}
else{
$GetLastRecordTime = Import-Csv -Path $CheckpointFile
$startTime = $GetLastRecordTime | ForEach-Object{
if($_.Key -eq $LogType){
$_.Value
}
}
return $startTime
}
}
# Function to update the checkpoint time with the last successful API call end time
function UpdateCheckpointTime($CheckpointFile, $LogType, $LastSuccessfulTime){
$checkpoints = Import-Csv -Path $CheckpointFile
$checkpoints | ForEach-Object{ if($_.Key -eq $LogType){$_.Value = $LastSuccessfulTime}}
$checkpoints.GetEnumerator() | Select-Object -Property Key,Value | Export-CSV -Path $CheckpointFile -NoTypeInformation
}
# Main Function to call the API and Post the response to the Log Analytics API
function Netskope () {
$customerId = $env:workspaceId
$sharedKey = $env:workspacekey
$apikey = $env:apikey
$uri = $env:uri
$tableName = "Netskope"
$timeInterval = [int]($env:timeInterval) * 60
$pageLimit = 5000
$skip = 0
$loggingOptions = $env:logTypes
$apitypes = @($loggingOptions.split(",").Trim())
$checkPointFile = ".\NetskopeCheckpoint.csv"
foreach($logtype in $apitypes){
$endTime = (Get-Date -Date ((Get-Date).DateTime) -UFormat %s)
$startTime = GetStartTime -CheckpointFile $checkPointFile -LogType $logtype -TimeInterval $timeInterval # function to create starttime
$alleventobjs = @()
$count = 0
Do {
$response = GetLogs -Uri $uri -ApiKey $apikey -StartTime $startTime -EndTime $endTime -LogType $logtype -Page $pageLimit -Skip $skip
$netskopeevents = $response.data
$dataLength = $response.data.Length
$alleventobjs += $netskopeevents
# Write-Host "$dataLength records added for '$logtype' events"
# If the API response length for the given log type is equal to the page limit, it indicates there are subsquent pages, continue while loop, and increment the skip value by the records already recieved for the subquent API requests
if($dataLength -eq $pageLimit){
$skip = $skip + $pageLimit
}
else {
# If the API response length for the given logtype is less than the page limit, it indicates there are no subsquent pages, break the while loop and move to the next logtype
$count = 1
$skip = 0
}
} while ($count -eq 0)
$allEventsLength = $alleventobjs.Length
if ($allEventsLength -ne 0){
$jsonPayload = $alleventobjs | ConvertTo-Json -Depth 3
$mbytes = ([System.Text.Encoding]::UTF8.GetBytes($jsonPayload)).Count/1024/1024
# Check the payload size, if under 30MB post to Log Analytics.
if (($mbytes -le 30)){
$responseCode = Post-LogAnalyticsData -customerId $customerId -sharedKey $sharedKey -body ([System.Text.Encoding]::UTF8.GetBytes($jsonPayload)) -logType $tableName
if ($responseCode -ne 200){
Write-Host "ERROR: Log Analytics POST, Status Code: $responseCode, unsuccessful."
}
else {
Write-Host "SUCCESS: $allEventsLength total '$logType' events posted to Log Analytics: $mbytes MB" -ForegroundColor Green
UpdateCheckpointTime -CheckpointFile $checkPointFile -LogType $logtype -LastSuccessfulTime $endTime
}
}
else {
Write-Host "ERROR: Log Analytics POST failed due to paylog exceeding 30Mb: $mbytes"
}
}
else {
$startInterval = (Get-Date 01.01.1970)+([System.TimeSpan]::fromseconds($startTime))
$endInterval = (Get-Date 01.01.1970)+([System.TimeSpan]::fromseconds($endTime))
Write-Host "INFO: No new '$logtype' records created between $startInterval and $endInterval"
UpdateCheckpointTime -CheckpointFile $checkPointFile -LogType $logtype -LastSuccessfulTime $endTime
}
}
}
# Function to build the authorization signature to post to Log Analytics
function Build-Signature ($customerId, $sharedKey, $date, $contentLength, $method, $contentType, $resource)
{
$xHeaders = "x-ms-date:" + $date;
$stringToHash = $method + "`n" + $contentLength + "`n" + $contentType + "`n" + $xHeaders + "`n" + $resource;
$bytesToHash = [Text.Encoding]::UTF8.GetBytes($stringToHash);
$keyBytes = [Convert]::FromBase64String($sharedKey);
$sha256 = New-Object System.Security.Cryptography.HMACSHA256;
$sha256.Key = $keyBytes;
$calculatedHash = $sha256.ComputeHash($bytesToHash);
$encodedHash = [Convert]::ToBase64String($calculatedHash);
$authorization = 'SharedKey {0}:{1}' -f $customerId,$encodedHash;
return $authorization;
}
# Function to POST the data payload to a Log Analytics workspace
function Post-LogAnalyticsData($customerId, $sharedKey, $body, $logType)
{
$TimeStampField = "DateValue"
$method = "POST";
$contentType = "application/json";
$resource = "/api/logs";
$rfc1123date = [DateTime]::UtcNow.ToString("r");
$contentLength = $body.Length;
$signature = Build-Signature -customerId $customerId -sharedKey $sharedKey -date $rfc1123date -contentLength $contentLength -method $method -contentType $contentType -resource $resource;
$uri = "https://$($customerId).ods.opinsights.azure.com$($resource)?api-version=2016-04-01";
$headers = @{
"Authorization" = $signature;
"Log-Type" = $logType;
"x-ms-date" = $rfc1123date;
"time-generated-field" = $TimeStampField;
};
$response = Invoke-WebRequest -Body $body -Uri $uri -Method $method -ContentType $contentType -Headers $headers -UseBasicParsing
return $response.StatusCode
}
# Execute the Function to pull Netskope alerts and events and post to a Log Analytics workspace
Netskope
# Write an information log with the current time.
Write-Host "PowerShell timer trigger function ran! TIME: $currentUTCtime"

Просмотреть файл

@ -0,0 +1,137 @@
{
"id": "Netskope",
"title": "Netskope",
"publisher": "Netskope",
"descriptionMarkdown": "The [Netskope Cloud Security Platform](https://www.netskope.com/platform) connector provides the capability to ingest Netskope logs and events into Azure Sentinel. The connector provides visibility into Netskope Platform Events and Alerts in Azure Sentinel to improve monitoring and investigation capabilities.",
"additionalRequirementBanner":"These queries are based on a Kusto Function to work as expected. Follow the steps to use this Kusto functions alias **Netskope**. [Follow these steps to get this Kusto functions.](https://aka.ms/sentinelgithubparsersnetskope)",
"graphQueries": [
{
"metricName": "Total data received",
"legend": "Netskope",
"baseQuery": "Netskope_CL"
}
],
"sampleQueries": [
{
"description" : "Top 10 Users",
"query": "Netskope\n | summarize count() by SrcUserName \n | top 10 by count_"
},
{
"description" : "Top 10 Alerts",
"query": "Netskope\n | where isnotempty(AlertName) \n | summarize count() by AlertName \n| top 10 by count_"
}
],
"dataTypes": [
{
"name": "Netskope_CL",
"lastDataReceivedQuery": "Netskope_CL\n | summarize Time = max(TimeGenerated)\n | where isnotempty(Time)"
}
],
"connectivityCriterias": [
{
"type": "IsConnectedQuery",
"value": [
"Netskope_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 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": "Netskope API Token",
"description": "A Netskope API Token is required. [See the documentation to learn more about Netskope API](https://innovatechcloud.goskope.com/docs/Netskope_Help/en/rest-api-v1-overview.html). **Note:** A Netskope account is required"
}
]
},
"instructionSteps": [
{
"title": "",
"description": ">**NOTE:** This connector uses Azure Functions to connect to Netskope to pull 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": ">This data connector depends on a parser based on a Kusto Function to work as expected. [Follow the steps](https://aka.ms/sentinelgithubparsersnetskope) to use the Kusto function alias, **Netskope**"
},
{
"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 Netskope API**\n\n [Follow these instructions](https://innovatechcloud.goskope.com/docs/Netskope_Help/en/rest-api-v2-overview.html) provided by Netskope to obtain an API Token. **Note:** A Netskope account is required"
},
{
"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 Netskope connector, have the Workspace ID and Workspace Primary Key (can be copied from the following), as well as the Netskope API Authorization Token, 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": "This method provides an automated deployment of the Netskope connector using an ARM Tempate.\n\n1. Click the **Deploy to Azure** button below. \n\n\t[![Deploy To Azure](https://aka.ms/deploytoazurebutton)](https://aka.ms/sentinelnetskopeazuredeploy)\n2. Select the preferred **Subscription**, **Resource Group** and **Location**. \n3. Enter the **Workspace ID**, **Workspace Key**, **API Key**, and **URI**.\n - Use the following schema for the `uri` value: `https://<Tenant Name>.goskope.com` Replace `<Tenant Name>` with your domain.\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 Timer Trigger accordingly (in the function.json file, post deployment) to prevent overlapping data ingestion.\n - The default **Log Types** is set to pull all 6 available log types (`alert, page, application, audit, infrastructure, network`), remove any are not required. \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.\n6. After successfully deploying the connector, download the Kusto Function to normalize the data fields. [Follow the steps](https://aka.ms/sentinelgithubparsersnetskope) to use the Kusto function alias, **Netskope**."
},
{
"title": "Option 2 - Manual Deployment of Azure Functions",
"description": "This method provides the step-by-step instructions to deploy the Netskope connector manually with Azure Function."
},
{
"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 **+ Add**.\n2. Select **Timer Trigger**.\n3. Enter a unique Function **Name** and modify the cron schedule, if needed. The default value is set to run the Function App every 5 minutes. (Note: the Timer trigger should match the `timeInterval` value below to prevent overlapping data), click **Create**.\n4. Click on **Code + Test** on the left pane. \n5. Copy the [Function App Code](https://raw.githubusercontent.com/rvanaparthi/netskope/main/azure-arm-templates/AzureFunctionNetskope/run.ps1) and paste into the Function App `run.ps1` editor.\n5. 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 six (6) application settings individually, with their respective string values (case-sensitive): \n\t\tapikey\n\t\tworkspaceID\n\t\tworkspaceKey\n\t\turi\n\t\ttimeInterval\n\t\tlogTypes\n> - Enter the URI that corresponds to your region. The `uri` value must follow the following schema: `https://<Tenant Name>.goskope.com` - There is no need to add subsquent parameters to the Uri, the Function App will dynamically append the parameteres in the proper format.\n> - Set the `timeInterval` (in minutes) to the default value of `5` to correspond to the default 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> - Set the `logTypes` to `alert, page, application, audit, infrastructure, network` - This list represents all the avaliable log types. Select the log types based on logging requirements, seperating each by a single comma.\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**.\n5. After successfully deploying the connector, download the Kusto Function to normalize the data fields. [Follow the steps](https://aka.ms/sentinelgithubparsersnetskope) to use the Kusto function alias, **Netskope**."
}
]
}

Просмотреть файл

@ -0,0 +1,235 @@
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"FunctionName": {
"defaultValue": "Netskope",
"type": "string"
},
"WorkspaceId": {
"type": "string",
"defaultValue": "<WorkspaceId>"
},
"Workspacekey": {
"type": "string",
"defaultValue": "<WorkspaceKey>"
},
"APIKey": {
"type": "string",
"defaultValue": "<API Key>"
},
"TimeInterval": {
"type": "string",
"defaultValue": "5"
},
"Uri": {
"type": "string",
"defaultValue": "https://<Tenant Name>.goskope.com"
},
"LogTypes": {
"type": "string",
"defaultValue": "alert,page,application,audit,infrastructure,network"
}
},
"variables": {
"FunctionName": "[concat(toLower(parameters('FunctionName')), uniqueString(resourceGroup().id))]"
},
"resources": [
{
"type": "Microsoft.Insights/components",
"apiVersion": "2015-05-01",
"name": "[variables('FunctionName')]",
"location": "[resourceGroup().location]",
"kind": "web",
"properties": {
"Application_Type": "web",
"ApplicationId": "[variables('FunctionName')]"
}
},
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2019-06-01",
"name": "[tolower(variables('FunctionName'))]",
"location": "[resourceGroup().location]",
"sku": {
"name": "Standard_LRS",
"tier": "Standard"
},
"kind": "StorageV2",
"properties": {
"networkAcls": {
"bypass": "AzureServices",
"virtualNetworkRules": [],
"ipRules": [],
"defaultAction": "Allow"
},
"supportsHttpsTrafficOnly": true,
"encryption": {
"services": {
"file": {
"keyType": "Account",
"enabled": true
},
"blob": {
"keyType": "Account",
"enabled": true
}
},
"keySource": "Microsoft.Storage"
}
}
},
{
"type": "Microsoft.Web/serverfarms",
"apiVersion": "2018-02-01",
"name": "[variables('FunctionName')]",
"location": "[resourceGroup().location]",
"sku": {
"name": "Y1",
"tier": "Dynamic"
},
"kind": "functionapp",
"properties": {
"name": "[variables('FunctionName')]",
"workerSize": "0",
"workerSizeId": "0",
"numberOfWorkers": "1"
}
},
{
"type": "Microsoft.Storage/storageAccounts/blobServices",
"apiVersion": "2019-06-01",
"name": "[concat(variables('FunctionName'), '/default')]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts', tolower(variables('FunctionName')))]"
],
"sku": {
"name": "Standard_LRS",
"tier": "Standard"
},
"properties": {
"cors": {
"corsRules": []
},
"deleteRetentionPolicy": {
"enabled": false
}
}
},
{
"type": "Microsoft.Storage/storageAccounts/fileServices",
"apiVersion": "2019-06-01",
"name": "[concat(variables('FunctionName'), '/default')]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts', tolower(variables('FunctionName')))]"
],
"sku": {
"name": "Standard_LRS",
"tier": "Standard"
},
"properties": {
"cors": {
"corsRules": []
}
}
},
{
"type": "Microsoft.Web/sites",
"apiVersion": "2018-11-01",
"name": "[variables('FunctionName')]",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts', tolower(variables('FunctionName')))]",
"[resourceId('Microsoft.Web/serverfarms', variables('FunctionName'))]",
"[resourceId('Microsoft.Insights/components', variables('FunctionName'))]"
],
"kind": "functionapp",
"identity": {
"type": "SystemAssigned"
},
"properties": {
"name": "[variables('FunctionName')]",
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('FunctionName'))]",
"httpsOnly": true,
"clientAffinityEnabled": true,
"alwaysOn": true
},
"resources": [
{
"apiVersion": "2018-11-01",
"type": "config",
"name": "appsettings",
"dependsOn": [
"[concat('Microsoft.Web/sites/', variables('FunctionName'))]"
],
"properties": {
"FUNCTIONS_EXTENSION_VERSION": "~3",
"FUNCTIONS_WORKER_RUNTIME": "powershell",
"APPINSIGHTS_INSTRUMENTATIONKEY": "[reference(resourceId('Microsoft.insights/components', variables('FunctionName')), '2015-05-01').InstrumentationKey]",
"APPLICATIONINSIGHTS_CONNECTION_STRING": "[reference(resourceId('microsoft.insights/components', variables('FunctionName')), '2015-05-01').ConnectionString]",
"AzureWebJobsStorage": "[concat('DefaultEndpointsProtocol=https;AccountName=', toLower(variables('FunctionName')),';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', toLower(variables('FunctionName'))), '2019-06-01').keys[0].value, ';EndpointSuffix=core.windows.net')]",
"WEBSITE_CONTENTAZUREFILECONNECTIONSTRING": "[concat('DefaultEndpointsProtocol=https;AccountName=', toLower(variables('FunctionName')),';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', toLower(variables('FunctionName'))), '2019-06-01').keys[0].value, ';EndpointSuffix=core.windows.net')]",
"WEBSITE_CONTENTSHARE": "[toLower(variables('FunctionName'))]",
"workspaceId": "[parameters('WorkspaceId')]",
"workspaceKey": "[parameters('Workspacekey')]",
"apikey": "[parameters('APIKey')]",
"uri": "[parameters('Uri')]",
"timeInterval": "[parameters('TimeInterval')]",
"logTypes": "[parameters('LogTypes')]",
"WEBSITE_RUN_FROM_PACKAGE": "https://github.com/rvanaparthi/netskope/blob/main/azure-arm-templates/AzureFunctionNetskope.zip?raw=true"
}
}
]
},
{
"type": "Microsoft.Web/sites/hostNameBindings",
"apiVersion": "2018-11-01",
"name": "[concat(variables('FunctionName'), '/', variables('FunctionName'), '.azurewebsites.net')]",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', variables('FunctionName'))]"
],
"properties": {
"siteName": "[variables('FunctionName')]",
"hostNameType": "Verified"
}
},
{
"type": "Microsoft.Storage/storageAccounts/blobServices/containers",
"apiVersion": "2019-06-01",
"name": "[concat(variables('FunctionName'), '/default/azure-webjobs-hosts')]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts/blobServices', variables('FunctionName'), 'default')]",
"[resourceId('Microsoft.Storage/storageAccounts', variables('FunctionName'))]"
],
"properties": {
"publicAccess": "None"
}
},
{
"type": "Microsoft.Storage/storageAccounts/blobServices/containers",
"apiVersion": "2019-06-01",
"name": "[concat(variables('FunctionName'), '/default/azure-webjobs-secrets')]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts/blobServices', variables('FunctionName'), 'default')]",
"[resourceId('Microsoft.Storage/storageAccounts', variables('FunctionName'))]"
],
"properties": {
"publicAccess": "None"
}
},
{
"type": "Microsoft.Storage/storageAccounts/fileServices/shares",
"apiVersion": "2019-06-01",
"name": "[concat(variables('FunctionName'), '/default/', tolower(variables('FunctionName')))]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts/fileServices', variables('FunctionName'), 'default')]",
"[resourceId('Microsoft.Storage/storageAccounts', variables('FunctionName'))]"
],
"properties": {
"shareQuota": 5120
}
}
]
}

Просмотреть файл

@ -0,0 +1,10 @@
{
"version": "2.0",
"managedDependency": {
"Enabled": true
},
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[1.*, 2.0.0)"
}
}

Просмотреть файл

@ -0,0 +1,20 @@
# Azure Functions profile.ps1
#
# This profile.ps1 will get executed every "cold start" of your Function App.
# "cold start" occurs when:
#
# * A Function App starts up for the very first time
# * A Function App starts up after being de-allocated due to inactivity
#
# You can define helper functions, run commands, or specify environment variables
# NOTE: any variables defined that are not environment variables will get reset after the first execution
# Authenticate with Azure PowerShell using MSI.
# Remove this if you are not planning on using MSI or Azure PowerShell.
if ($env:MSI_SECRET -and (Get-Module -ListAvailable Az.Accounts)) {
    Connect-AzAccount -Identity
}
# Uncomment the next line to enable legacy AzureRm alias in Azure PowerShell.
# Enable-AzureRmAlias
# You can also define functions or aliases that can be referenced in any of your PowerShell functions.

Просмотреть файл

@ -0,0 +1,7 @@
# This file enables modules to be automatically managed by the Functions service.
# See https://aka.ms/functionsmanageddependency for additional information.
#
@{
# For latest supported version, go to 'https://www.powershellgallery.com/packages/Az'.
'Az' = '4.*'
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу