This commit is contained in:
dicolanl 2021-02-27 00:18:29 +00:00
Родитель 83525d19a7
Коммит 58b3642d56
19 изменённых файлов: 641 добавлений и 7 удалений

6
.vscode/extensions.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1,6 @@
{
"recommendations": [
"ms-azuretools.vscode-azurefunctions",
"ms-vscode.PowerShell"
]
}

33
.vscode/launch.json поставляемый
Просмотреть файл

@ -8,12 +8,17 @@
"name": "Launch Program",
"type": "node",
"request": "launch",
"args": ["${relativeFile}"],
"runtimeArgs": ["--nolazy", "-r", "ts-node/register"],
"args": [
"${relativeFile}"
],
"runtimeArgs": [
"--nolazy",
"-r",
"ts-node/register"
],
"sourceMaps": true,
"cwd": "${workspaceRoot}",
"protocol": "inspector",
"protocol": "inspector"
},
{
"type": "node",
@ -26,7 +31,11 @@
"--colors",
"${workspaceFolder}/.script/test"
],
"runtimeArgs": ["--nolazy", "-r", "ts-node/register"],
"runtimeArgs": [
"--nolazy",
"-r",
"ts-node/register"
],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
},
@ -41,9 +50,21 @@
"--colors",
"${file}"
],
"runtimeArgs": ["--nolazy", "-r", "ts-node/register"],
"runtimeArgs": [
"--nolazy",
"-r",
"ts-node/register"
],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
},
{
"name": "Attach to PowerShell Functions",
"type": "PowerShell",
"request": "attach",
"customPipeName": "AzureFunctionsPSWorker",
"runspaceId": 1,
"preLaunchTask": "func: host start"
}
]
}

6
.vscode/settings.json поставляемый
Просмотреть файл

@ -1,3 +1,7 @@
{
"powershell.codeFormatting.addWhitespaceAroundPipe": true
"powershell.codeFormatting.addWhitespaceAroundPipe": true,
"azureFunctions.deploySubpath": "DataConnectors\\AADUserInfo",
"azureFunctions.projectLanguage": "PowerShell",
"azureFunctions.projectRuntime": "~3",
"debug.internalConsoleOptions": "neverOpen"
}

14
.vscode/tasks.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1,14 @@
{
"version": "2.0.0",
"tasks": [
{
"type": "func",
"command": "host start",
"problemMatcher": "$func-powershell-watch",
"isBackground": true,
"options": {
"cwd": "${workspaceFolder}/DataConnectors\\AADUserInfo"
}
}
]
}

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

@ -0,0 +1,4 @@
.git*
.vscode
local.settings.json
test

6
DataConnectors/AADUserInfo/.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,6 @@
# Azure Functions artifacts
bin
obj
appsettings.json
local.settings.json

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

@ -0,0 +1,10 @@
{
"bindings": [
{
"name": "Timer",
"type": "timerTrigger",
"direction": "in",
"schedule": "0 */1440 * * * *"
}
]
}

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

@ -0,0 +1,11 @@
# TimerTrigger - PowerShell
The `TimerTrigger` makes it incredibly easy to have your functions executed on a schedule. This sample demonstrates a simple use case of calling your function every 5 minutes.
## How it works
For a `TimerTrigger` to work, you provide a schedule in the form of a [cron expression](https://en.wikipedia.org/wiki/Cron#CRON_expression)(See the link for full details). A cron expression is a string with 6 separate expressions which represent a given schedule via patterns. The pattern we use to represent every 5 minutes is `0 */5 * * * *`. This, in plain text, means: "When seconds is equal to 0, minutes is divisible by 5, for any hour, day of the month, month, day of the week, or year".
## Learn more
<TODO> Documentation

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

@ -0,0 +1,83 @@
# 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' porperty is 'true' when the current function invocation is later than scheduled.
if ($Timer.IsPastDue) {
Write-Host "PowerShell timer is running late!"
}
Import-Module AzureAD -UseWindowsPowerShell
# Function to build the Authorization signature for the Log Analytics Data Connector API
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
# Dispose SHA256 from heap before return.
$sha256.Dispose()
return $authorization
}
# Function to create and invoke an API POST request to the Log Analytics Data Connector API
Function Post-LogAnalyticsData($customerId, $sharedKey, $body, $logType)
{
$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;
}
$response = Invoke-RestMethod -Uri $uri -Method $method -ContentType $contentType -Headers $headers -Body $body
#$response = Invoke-WebRequest -Uri $uri -Method $method -ContentType $contentType -Headers $headers -Body $body -UseBasicParsing
return $response.StatusCode
}
# Get Managed Service Identity info from Azure Functions Application Settings
$msiEndpoint = $env:MSI_ENDPOINT
$msiSecret = $env:MSI_SECRET
# Define the Log Analytics Workspace ID and Key
$CustomerId = $env:workspaceId
$SharedKey = $env:workspaceKey
connect-azaccount -identity
$context = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile.DefaultContext
$aadToken = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate($context.Account, $context.Environment, $context.Tenant.Id.ToString(), $null, [Microsoft.Azure.Commands.Common.Authentication.ShowDialog]::Never, $null, "https://graph.windows.net").AccessToken
Connect-AzureAD -AadAccessToken $aadToken -AccountId $context.Account.Id -TenantId $context.tenant.id
$Users = Get-AzureADUser -All $True
$json = ConvertTo-Json $Users -Depth 3
Post-LogAnalyticsData -customerId $customerId -sharedKey $sharedKey -body ([System.Text.Encoding]::UTF8.GetBytes($json)) -logType "AADUserInfov2"
# Write an information log with the current time.
Write-Host "PowerShell timer trigger function ran! TIME: $currentUTCtime"

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

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

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

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

@ -0,0 +1,88 @@
# Deploy a Function App for collecting Azure AD User Information data into Azure Sentinel
This function app run daily, query Azure AD for all users and write the information to Log Analyitcs.
Note: There is a parser avaialbe [here](https://github.com/Azure/Azure-Sentinel/blob/master/Parsers/AADUserInfo/AADUserInfo.txt)
### Deploy the Function App
The easiest way is via the provided ARM templates:
#### 1: Deploy via Azure ARM Template
1. Deploy the template.
<a href="https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2FAzure-Sentinel%2Fmaster%2FDataConnectors%2FAADUserInfo%2Fazuredeploy.json" target="_blank">
<img src="https://aka.ms/deploytoazurebutton""/>
</a>
2. Deploy permissions for the function to the Key Vault.
<a href="https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2FAzure-Sentinel%2Fmaster%2FDataConnectors%2FAADUserInfo%2Fazuredeploy_kv.json" target="_blank">
<img src="https://aka.ms/deploytoazurebutton""/>
</a>
Alternatively you can deploy the elements manually.
#### 2: Deploy via VS Code
Note: You will need to prepare VS code for Azure function development. See https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-first-function-powershell#prerequisites
1. Download the [Zip](https://github.com/Azure/Azure-Sentinel/blob/master/DataConnectors/AADUserInfo/AADUserInfo_template.zip?raw=true) file of the Azure Funciton app from Github.
2. Extract to a location on your local host.
3. Open VS Code.
4. Click File -> Open Folder.
5. Select the top level folder from extracted files.
6. Type Crtl+Shift+P.
7. Click Azure Functions: Deploy to function app. You maybe asked to sign in to Azure.
8. Click Create New function app in Azure (advanced).
9. Provide a unique name like "AADUserInfo". Press Enter.
10. Click Windows.
11. Click Consumption.
12. Click PowerShell.
13. Click Create new Resource Group.
14. Press enter to accept the name.
15. Click Create a new storage Account.
16. Press enter to accept the name.
17. Click Create new Application Insights resource.
18. Press enter to accept the name.
19. Pick a location to deploy in.
20. Deployment will begin.
21. Wait for the deployment to complete, then click upload settings in the bottom right.
22. Click yes to all to upload.
23. Go to the Azure Portal.
24. Go to the resource group that was created. Click the Function.
25. Click Stop.
26. Click Identity.
27. Click On under system assigned. Click Save. Click Yes.
29. Click Configuration
30. Click General Settings.
31. Change Platform to 64 Bit. Click Save.
### Create a Key Vault
1. Go to the Azure Portal.
2. Go to the resource group that was created. Click Add.
3. Type Key Vault.
4. Create a Key vault.
5. Go to the resource created.
6. Click Access Policies.
7. Click Add Access Policy.
8. Select Secret Management from Configure from template.
9. Click Select Principal.
10. Search for the name of the function app. Click Select.
11. Click Add.
12. Click Save.
13. Click Secrets.
14. Click Generate.
15. Enter WorkspaceKey. Paste in your Azure Sentinel Workspace Key. Click Create.
16. Click Generate.
17. Click WorkspaceKey and copy the current version string to a temporary location.
### Configure Settings for the Function
1. Go to the Azure Portal.
2. Go to the resource group that was created. Click the Function.
3. Click Configuration.
4. Click edit next to workspaceKey.
5. Update the value using the string copied from KeyVault.
* @Microsoft.KeyVault(SecretUri=https://<dnsname>/secrets/workspaceKey/<versionstring>)
6. Click Ok.
7. Click edit next to workspaceId.
8. Update the value with your Sentinel Workspace Id.
9. Click Ok.
11. Click Save.
If sucessfully deployed you should start to see events appear in your Azure Sentinel workpsace as soon as they are generated.
If you run into issues there are a number of options for [monitoring](https://docs.microsoft.com/en-us/azure/azure-functions/functions-monitoring?tabs=cmd) and [deugging](https://docs.microsoft.com/en-us/azure/azure-functions/functions-debug-powershell-local) your Function App.

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

@ -0,0 +1,251 @@
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"FunctionName": {
"defaultValue": "AADUserInfo",
"type": "string"
},
"workspaceID": {
"type": "string",
"defaultValue": "<workspaceID>"
},
"workspaceKey": {
"type": "string",
"defaultValue": "<workspaceKey>"
}
},
"variables": {
},
"resources": [
{
"type": "Microsoft.Insights/components",
"apiVersion": "2015-05-01",
"name": "[parameters('FunctionName')]",
"location": "[resourceGroup().location]",
"kind": "web",
"properties": {
"Application_Type": "web",
"ApplicationId": "[parameters('FunctionName')]"
}
},
{
"type": "Microsoft.KeyVault/vaults",
"apiVersion": "2016-10-01",
"name": "[parameters('FunctionName')]",
"location": "[resourceGroup().location]",
"properties": {
"sku": {
"family": "A",
"name": "standard"
},
"tenantId": "[subscription().tenantId]",
"enabledForDeployment": false,
"enabledForDiskEncryption": false,
"enabledForTemplateDeployment": true,
"enableSoftDelete": true,
"accessPolicies": [
]
}
},
{
"type": "Microsoft.KeyVault/vaults/secrets",
"apiVersion": "2016-10-01",
"name": "[concat(parameters('FunctionName'), '/workspaceKey')]",
"dependsOn": [
"[resourceId('Microsoft.KeyVault/vaults', parameters('FunctionName'))]"
],
"properties": {
"value": "[parameters('workspaceKey')]",
"contentType": "string",
"attributes": {
"enabled": true
}
}
},
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2019-06-01",
"name": "[tolower(parameters('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": "[parameters('FunctionName')]",
"location": "[resourceGroup().location]",
"sku": {
"name": "Y1",
"tier": "Dynamic"
},
"kind": "functionapp",
"properties": {
"name": "[parameters('FunctionName')]",
"workerSize": "0",
"workerSizeId": "0",
"numberOfWorkers": "1"
}
},
{
"type": "Microsoft.Storage/storageAccounts/blobServices",
"apiVersion": "2019-06-01",
"name": "[concat(parameters('FunctionName'), '/default')]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts', tolower(parameters('FunctionName')))]"
],
"sku": {
"name": "Standard_LRS",
"tier": "Standard"
},
"properties": {
"cors": {
"corsRules": [
]
},
"deleteRetentionPolicy": {
"enabled": false
}
}
},
{
"type": "Microsoft.Storage/storageAccounts/fileServices",
"apiVersion": "2019-06-01",
"name": "[concat(parameters('FunctionName'), '/default')]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts', tolower(parameters('FunctionName')))]"
],
"sku": {
"name": "Standard_LRS",
"tier": "Standard"
},
"properties": {
"cors": {
"corsRules": [
]
}
}
},
{
"type": "Microsoft.Web/sites",
"apiVersion": "2018-11-01",
"name": "[parameters('FunctionName')]",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts', tolower(parameters('FunctionName')))]",
"[resourceId('Microsoft.Web/serverfarms', parameters('FunctionName'))]",
"[resourceId('Microsoft.KeyVault/vaults', parameters('FunctionName'))]",
"[resourceId('Microsoft.Insights/components', parameters('FunctionName'))]"
],
"kind": "functionapp",
"identity": {
"type": "SystemAssigned"
},
"properties": {
"name": "[parameters('FunctionName')]",
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('FunctionName'))]",
"httpsOnly": true,
"clientAffinityEnabled": true
},
"resources": [
{
"apiVersion": "2018-11-01",
"type": "config",
"name": "appsettings",
"dependsOn": [
"[concat('Microsoft.Web/sites/', parameters('FunctionName'))]"
],
"properties": {
"use32BitWorkerProcess": false,
"FUNCTIONS_EXTENSION_VERSION": "~3",
"FUNCTIONS_WORKER_RUNTIME": "powershell",
"APPINSIGHTS_INSTRUMENTATIONKEY": "[reference(resourceId('Microsoft.insights/components', parameters('FunctionName')), '2015-05-01').InstrumentationKey]",
"APPLICATIONINSIGHTS_CONNECTION_STRING": "[reference(resourceId('microsoft.insights/components', parameters('FunctionName')), '2015-05-01').ConnectionString]",
"AzureWebJobsStorage": "[concat('DefaultEndpointsProtocol=https;AccountName=', toLower(parameters('FunctionName')),';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', toLower(parameters('FunctionName'))), '2019-06-01').keys[0].value, ';EndpointSuffix=core.windows.net')]",
"WEBSITE_CONTENTAZUREFILECONNECTIONSTRING": "[concat('DefaultEndpointsProtocol=https;AccountName=', toLower(parameters('FunctionName')),';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', toLower(parameters('FunctionName'))), '2019-06-01').keys[0].value, ';EndpointSuffix=core.windows.net')]",
"WEBSITE_CONTENTSHARE": "[toLower(parameters('FunctionName'))]",
"workspaceID": "[parameters('workspaceID')]",
"workspaceKey": "[concat('@Microsoft.KeyVault(SecretUri=', reference(resourceId('Microsoft.KeyVault/vaults/secrets', parameters('FunctionName'), 'workspaceKey')).SecretUriWithVersion, ')')]",
"WEBSITE_RUN_FROM_PACKAGE": "https://github.com/Azure/Azure-Sentinel/blob/master/DataConnectors/AADUserInfo/AADUserInfo_template.zip?raw=true" }
}
]
},
{
"type": "Microsoft.Web/sites/hostNameBindings",
"apiVersion": "2018-11-01",
"name": "[concat(parameters('FunctionName'), '/', parameters('FunctionName'), '.azurewebsites.net')]",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', parameters('FunctionName'))]"
],
"properties": {
"siteName": "[parameters('FunctionName')]",
"hostNameType": "Verified"
}
},
{
"type": "Microsoft.Storage/storageAccounts/blobServices/containers",
"apiVersion": "2019-06-01",
"name": "[concat(parameters('FunctionName'), '/default/azure-webjobs-hosts')]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts/blobServices', parameters('FunctionName'), 'default')]",
"[resourceId('Microsoft.Storage/storageAccounts', parameters('FunctionName'))]"
],
"properties": {
"publicAccess": "None"
}
},
{
"type": "Microsoft.Storage/storageAccounts/blobServices/containers",
"apiVersion": "2019-06-01",
"name": "[concat(parameters('FunctionName'), '/default/azure-webjobs-secrets')]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts/blobServices', parameters('FunctionName'), 'default')]",
"[resourceId('Microsoft.Storage/storageAccounts', parameters('FunctionName'))]"
],
"properties": {
"publicAccess": "None"
}
},
{
"type": "Microsoft.Storage/storageAccounts/fileServices/shares",
"apiVersion": "2019-06-01",
"name": "[concat(parameters('FunctionName'), '/default/', tolower(parameters('FunctionName')))]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts/fileServices', parameters('FunctionName'), 'default')]",
"[resourceId('Microsoft.Storage/storageAccounts', parameters('FunctionName'))]"
],
"properties": {
"shareQuota": 5120
}
}
]
}

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

@ -0,0 +1,45 @@
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"FunctionName": {
"defaultValue": "AADUserInfo",
"type": "String"
}
},
"variables": {
},
"resources": [
{
"type": "Microsoft.KeyVault/vaults/accessPolicies",
"apiVersion": "2016-10-01",
"name": "[concat(parameters('FunctionName'), '/add')]",
"properties": {
"accessPolicies": [
{
"tenantId": "[subscription().tenantId]",
"objectId": "[reference(concat(resourceId('Microsoft.Web/sites', parameters('FunctionName')), '/providers/Microsoft.ManagedIdentity/Identities/default'), '2018-11-30').principalId]",
"permissions": {
"keys": [
],
"secrets": [
"Get",
"List",
"Set",
"Delete",
"Recover",
"Backup",
"Restore"
],
"certificates": [
]
}
}
],
"enabledForDeployment": false,
"enabledForDiskEncryption": false,
"enabledForTemplateDeployment": true
}
}
]
}

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

@ -0,0 +1,18 @@
{
"version": "2.0",
"logging": {
"applicationInsights": {
"samplingSettings": {
"isEnabled": true,
"excludedTypes": "Request"
}
}
},
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[1.*, 2.0.0)"
},
"managedDependency": {
"enabled": true
}
}

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

@ -0,0 +1,22 @@
# 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) {
Disable-AzContextAutosave -Scope Process | Out-Null
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,4 @@
{
"$schema": "http://json.schemastore.org/proxies",
"proxies": {}
}

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

@ -0,0 +1,7 @@
# This file enables modules to be automatically managed by the Functions service.
# See https://aka.ms/functionsmanageddependency for additional information.
#
@{
'Az' = '5.*'
'AzureAD' = '2.*'
}

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

@ -0,0 +1,40 @@
// Usage Instruction :
// Paste below query in log analytics, click on Save button and select as Function from drop down by specifying function name and alias as AADUserInfo.
// Function usually takes 10-15 minutes to activate. You can then use function alias from any other queries (e.g. AADUserInfo | take 10).
// Reference : Using functions in Azure monitor log queries : https://docs.microsoft.com/azure/azure-monitor/log-query/functions
AADUserInfo_CL
| summarize arg_max(TimeGenerated, *) by ObjectId_g
| project TimeGenerated,
ExtensionProperty_createdDateTime=columnifexists('ExtensionProperty_createdDateTime_s', ""),
ExtensionProperty_userIdentities=columnifexists('ExtensionProperty_userIdentities_s', ""),
ExtensionProperty_onPremisesDistinguishedName=columnifexists('ExtensionProperty_onPremisesDistinguishedName_s', ""),
ObjectId=columnifexists('ObjectId_g', ""),
ObjectType=columnifexists('ObjectType_s', ""),
AccountEnabled=columnifexists('AccountEnabled_b', ""),
DirSyncEnabled=columnifexists('DirSyncEnabled_b', ""),
DisplayName=columnifexists('DisplayName_s', ""),
GivenName=columnifexists('GivenName_s', ""),
MailNickName=columnifexists('MailNickName_s', ""),
OnPremisesSecurityIdentifier=columnifexists('OnPremisesSecurityIdentifier_s', ""),
PasswordPolicies=columnifexists('PasswordPolicies_s', ""),
ProxyAddresses=columnifexists('ProxyAddresses_s', ""),
RefreshTokensValidFromDateTime=columnifexists('RefreshTokensValidFromDateTime_t', ""),
SignInNames=columnifexists('SignInNames_s', ""),
Surname=columnifexists('Surname_s', ""),
UserPrincipalName=columnifexists('UserPrincipalName_s', ""),
UserType=columnifexists('UserType_s', ""),
CompanyName=columnifexists('CompanyName_s', ""),
Department=columnifexists('Department_s', ""),
JobTitle=columnifexists('JobTitle_s', ""),
Mail=columnifexists('Mail_s', ""),
SipProxyAddress=columnifexists('SipProxyAddress_s', ""),
UsageLocation=columnifexists('UsageLocation_s', ""),
PasswordProfile=columnifexists('PasswordProfile_s', ""),
UserState=columnifexists('UserState_s', ""),
City=columnifexists('City_s', ""),
Mobile=columnifexists('Mobile_s', ""),
PhysicalDeliveryOfficeName=columnifexists('PhysicalDeliveryOfficeName_s', ""),
PostalCode=columnifexists('PostalCode_s', ""),
State=columnifexists('State_s', ""),
StreetAddress=columnifexists('StreetAddress_s', ""),
Country=columnifexists('Country_s', "")