├── .github └── workflows │ └── build-dotnet-core.yml ├── .gitignore ├── .vscode ├── extensions.json ├── launch.json ├── settings.json └── tasks.json ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SECURITY.md ├── media └── private-function-diagram.jpg ├── src ├── OrderProcessingFunctions.cs ├── host.json ├── private-endpoints.csproj ├── sample.csv └── sample.local.settings.json └── template ├── azuredeploy.json └── azuredeploy.parameters.json /.github/workflows/build-dotnet-core.yml: -------------------------------------------------------------------------------- 1 | name: .NET Core 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | paths-ignore: ./template 7 | pull_request: 8 | branches: [master] 9 | paths-ignore: ./template 10 | 11 | jobs: 12 | build: 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v2 17 | - name: Setup .NET Core 18 | uses: actions/setup-dotnet@v1 19 | with: 20 | dotnet-version: 3.1.101 21 | - name: Install dependencies 22 | working-directory: ./src 23 | run: dotnet restore 24 | - name: Build 25 | working-directory: ./src 26 | run: dotnet build --configuration Release --no-restore 27 | - name: Test 28 | working-directory: ./src 29 | run: dotnet test --no-restore --verbosity normal 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # Azure Functions localsettings file 7 | local.settings.json 8 | 9 | # User-specific files 10 | *.rsuser 11 | *.suo 12 | *.user 13 | *.userosscache 14 | *.sln.docstates 15 | 16 | # User-specific files (MonoDevelop/Xamarin Studio) 17 | *.userprefs 18 | 19 | # Mono auto generated files 20 | mono_crash.* 21 | 22 | # Build results 23 | [Dd]ebug/ 24 | [Dd]ebugPublic/ 25 | [Rr]elease/ 26 | [Rr]eleases/ 27 | x64/ 28 | x86/ 29 | [Aa][Rr][Mm]/ 30 | [Aa][Rr][Mm]64/ 31 | bld/ 32 | [Bb]in/ 33 | [Oo]bj/ 34 | [Ll]og/ 35 | [Ll]ogs/ 36 | 37 | # Visual Studio 2015/2017 cache/options directory 38 | .vs/ 39 | # Uncomment if you have tasks that create the project's static files in wwwroot 40 | #wwwroot/ 41 | 42 | # Visual Studio 2017 auto generated files 43 | Generated\ Files/ 44 | 45 | # MSTest test Results 46 | [Tt]est[Rr]esult*/ 47 | [Bb]uild[Ll]og.* 48 | 49 | # NUnit 50 | *.VisualState.xml 51 | TestResult.xml 52 | nunit-*.xml 53 | 54 | # Build Results of an ATL Project 55 | [Dd]ebugPS/ 56 | [Rr]eleasePS/ 57 | dlldata.c 58 | 59 | # Benchmark Results 60 | BenchmarkDotNet.Artifacts/ 61 | 62 | # .NET Core 63 | project.lock.json 64 | project.fragment.lock.json 65 | artifacts/ 66 | 67 | # StyleCop 68 | StyleCopReport.xml 69 | 70 | # Files built by Visual Studio 71 | *_i.c 72 | *_p.c 73 | *_h.h 74 | *.ilk 75 | *.meta 76 | *.obj 77 | *.iobj 78 | *.pch 79 | *.pdb 80 | *.ipdb 81 | *.pgc 82 | *.pgd 83 | *.rsp 84 | *.sbr 85 | *.tlb 86 | *.tli 87 | *.tlh 88 | *.tmp 89 | *.tmp_proj 90 | *_wpftmp.csproj 91 | *.log 92 | *.vspscc 93 | *.vssscc 94 | .builds 95 | *.pidb 96 | *.svclog 97 | *.scc 98 | 99 | # Chutzpah Test files 100 | _Chutzpah* 101 | 102 | # Visual C++ cache files 103 | ipch/ 104 | *.aps 105 | *.ncb 106 | *.opendb 107 | *.opensdf 108 | *.sdf 109 | *.cachefile 110 | *.VC.db 111 | *.VC.VC.opendb 112 | 113 | # Visual Studio profiler 114 | *.psess 115 | *.vsp 116 | *.vspx 117 | *.sap 118 | 119 | # Visual Studio Trace Files 120 | *.e2e 121 | 122 | # TFS 2012 Local Workspace 123 | $tf/ 124 | 125 | # Guidance Automation Toolkit 126 | *.gpState 127 | 128 | # ReSharper is a .NET coding add-in 129 | _ReSharper*/ 130 | *.[Rr]e[Ss]harper 131 | *.DotSettings.user 132 | 133 | # TeamCity is a build add-in 134 | _TeamCity* 135 | 136 | # DotCover is a Code Coverage Tool 137 | *.dotCover 138 | 139 | # AxoCover is a Code Coverage Tool 140 | .axoCover/* 141 | !.axoCover/settings.json 142 | 143 | # Visual Studio code coverage results 144 | *.coverage 145 | *.coveragexml 146 | 147 | # NCrunch 148 | _NCrunch_* 149 | .*crunch*.local.xml 150 | nCrunchTemp_* 151 | 152 | # MightyMoose 153 | *.mm.* 154 | AutoTest.Net/ 155 | 156 | # Web workbench (sass) 157 | .sass-cache/ 158 | 159 | # Installshield output folder 160 | [Ee]xpress/ 161 | 162 | # DocProject is a documentation generator add-in 163 | DocProject/buildhelp/ 164 | DocProject/Help/*.HxT 165 | DocProject/Help/*.HxC 166 | DocProject/Help/*.hhc 167 | DocProject/Help/*.hhk 168 | DocProject/Help/*.hhp 169 | DocProject/Help/Html2 170 | DocProject/Help/html 171 | 172 | # Click-Once directory 173 | publish/ 174 | 175 | # Publish Web Output 176 | *.[Pp]ublish.xml 177 | *.azurePubxml 178 | # Note: Comment the next line if you want to checkin your web deploy settings, 179 | # but database connection strings (with potential passwords) will be unencrypted 180 | *.pubxml 181 | *.publishproj 182 | 183 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 184 | # checkin your Azure Web App publish settings, but sensitive information contained 185 | # in these scripts will be unencrypted 186 | PublishScripts/ 187 | 188 | # NuGet Packages 189 | *.nupkg 190 | # NuGet Symbol Packages 191 | *.snupkg 192 | # The packages folder can be ignored because of Package Restore 193 | **/[Pp]ackages/* 194 | # except build/, which is used as an MSBuild target. 195 | !**/[Pp]ackages/build/ 196 | # Uncomment if necessary however generally it will be regenerated when needed 197 | #!**/[Pp]ackages/repositories.config 198 | # NuGet v3's project.json files produces more ignorable files 199 | *.nuget.props 200 | *.nuget.targets 201 | 202 | # Microsoft Azure Build Output 203 | csx/ 204 | *.build.csdef 205 | 206 | # Microsoft Azure Emulator 207 | ecf/ 208 | rcf/ 209 | 210 | # Windows Store app package directories and files 211 | AppPackages/ 212 | BundleArtifacts/ 213 | Package.StoreAssociation.xml 214 | _pkginfo.txt 215 | *.appx 216 | *.appxbundle 217 | *.appxupload 218 | 219 | # Visual Studio cache files 220 | # files ending in .cache can be ignored 221 | *.[Cc]ache 222 | # but keep track of directories ending in .cache 223 | !?*.[Cc]ache/ 224 | 225 | # Others 226 | ClientBin/ 227 | ~$* 228 | *~ 229 | *.dbmdl 230 | *.dbproj.schemaview 231 | *.jfm 232 | *.pfx 233 | *.publishsettings 234 | orleans.codegen.cs 235 | 236 | # Including strong name files can present a security risk 237 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 238 | #*.snk 239 | 240 | # Since there are multiple workflows, uncomment next line to ignore bower_components 241 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 242 | #bower_components/ 243 | 244 | # RIA/Silverlight projects 245 | Generated_Code/ 246 | 247 | # Backup & report files from converting an old project file 248 | # to a newer Visual Studio version. Backup files are not needed, 249 | # because we have git ;-) 250 | _UpgradeReport_Files/ 251 | Backup*/ 252 | UpgradeLog*.XML 253 | UpgradeLog*.htm 254 | ServiceFabricBackup/ 255 | *.rptproj.bak 256 | 257 | # SQL Server files 258 | *.mdf 259 | *.ldf 260 | *.ndf 261 | 262 | # Business Intelligence projects 263 | *.rdl.data 264 | *.bim.layout 265 | *.bim_*.settings 266 | *.rptproj.rsuser 267 | *- [Bb]ackup.rdl 268 | *- [Bb]ackup ([0-9]).rdl 269 | *- [Bb]ackup ([0-9][0-9]).rdl 270 | 271 | # Microsoft Fakes 272 | FakesAssemblies/ 273 | 274 | # GhostDoc plugin setting file 275 | *.GhostDoc.xml 276 | 277 | # Node.js Tools for Visual Studio 278 | .ntvs_analysis.dat 279 | node_modules/ 280 | 281 | # Visual Studio 6 build log 282 | *.plg 283 | 284 | # Visual Studio 6 workspace options file 285 | *.opt 286 | 287 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 288 | *.vbw 289 | 290 | # Visual Studio LightSwitch build output 291 | **/*.HTMLClient/GeneratedArtifacts 292 | **/*.DesktopClient/GeneratedArtifacts 293 | **/*.DesktopClient/ModelManifest.xml 294 | **/*.Server/GeneratedArtifacts 295 | **/*.Server/ModelManifest.xml 296 | _Pvt_Extensions 297 | 298 | # Paket dependency manager 299 | .paket/paket.exe 300 | paket-files/ 301 | 302 | # FAKE - F# Make 303 | .fake/ 304 | 305 | # CodeRush personal settings 306 | .cr/personal 307 | 308 | # Python Tools for Visual Studio (PTVS) 309 | __pycache__/ 310 | *.pyc 311 | 312 | # Cake - Uncomment if you are using it 313 | # tools/** 314 | # !tools/packages.config 315 | 316 | # Tabs Studio 317 | *.tss 318 | 319 | # Telerik's JustMock configuration file 320 | *.jmconfig 321 | 322 | # BizTalk build output 323 | *.btp.cs 324 | *.btm.cs 325 | *.odx.cs 326 | *.xsd.cs 327 | 328 | # OpenCover UI analysis results 329 | OpenCover/ 330 | 331 | # Azure Stream Analytics local run output 332 | ASALocalRun/ 333 | 334 | # MSBuild Binary and Structured Log 335 | *.binlog 336 | 337 | # NVidia Nsight GPU debugger configuration file 338 | *.nvuser 339 | 340 | # MFractors (Xamarin productivity tool) working folder 341 | .mfractor/ 342 | 343 | # Local History for Visual Studio 344 | .localhistory/ 345 | 346 | # BeatPulse healthcheck temp database 347 | healthchecksdb 348 | 349 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 350 | MigrationBackup/ 351 | 352 | # Ionide (cross platform F# VS Code tools) working folder 353 | .ionide/ 354 | 355 | 356 | # Azure Functions Core Tools 357 | src/azure-functions-core-tools/* 358 | template/azure-functions-core-tools/* 359 | azure-functions-core-tools/* -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "ms-azuretools.vscode-azurefunctions", 4 | "ms-dotnettools.csharp" 5 | ] 6 | } -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Attach to .NET Functions", 6 | "type": "coreclr", 7 | "request": "attach", 8 | "processId": "${command:azureFunctions.pickProcess}" 9 | } 10 | ] 11 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "azureFunctions.deploySubpath": "src/bin/Release/netcoreapp3.1/publish", 3 | "azureFunctions.projectLanguage": "C#", 4 | "azureFunctions.projectRuntime": "~3", 5 | "debug.internalConsoleOptions": "neverOpen", 6 | "azureFunctions.preDeployTask": "publish" 7 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "options": { 4 | "cwd": "src" 5 | }, 6 | "tasks": [ 7 | { 8 | "label": "clean", 9 | "command": "dotnet", 10 | "args": [ 11 | "clean", 12 | "/property:GenerateFullPaths=true", 13 | "/consoleloggerparameters:NoSummary" 14 | ], 15 | "type": "process", 16 | "problemMatcher": "$msCompile" 17 | }, 18 | { 19 | "label": "build", 20 | "command": "dotnet", 21 | "args": [ 22 | "build", 23 | "/property:GenerateFullPaths=true", 24 | "/consoleloggerparameters:NoSummary" 25 | ], 26 | "type": "process", 27 | "dependsOn": "clean", 28 | "group": { 29 | "kind": "build", 30 | "isDefault": true 31 | }, 32 | "problemMatcher": "$msCompile" 33 | }, 34 | { 35 | "label": "clean release", 36 | "command": "dotnet", 37 | "args": [ 38 | "clean", 39 | "--configuration", 40 | "Release", 41 | "/property:GenerateFullPaths=true", 42 | "/consoleloggerparameters:NoSummary" 43 | ], 44 | "type": "process", 45 | "problemMatcher": "$msCompile" 46 | }, 47 | { 48 | "label": "publish", 49 | "command": "dotnet", 50 | "args": [ 51 | "publish", 52 | "--configuration", 53 | "Release", 54 | "/property:GenerateFullPaths=true", 55 | "/consoleloggerparameters:NoSummary" 56 | ], 57 | "type": "process", 58 | "dependsOn": "clean release", 59 | "problemMatcher": "$msCompile" 60 | }, 61 | { 62 | "type": "func", 63 | "dependsOn": "build", 64 | "options": { 65 | "cwd": "${workspaceFolder}/src/bin/Debug/netcoreapp3.1" 66 | }, 67 | "command": "host start", 68 | "isBackground": true, 69 | "problemMatcher": "$func-watch" 70 | } 71 | ] 72 | } -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | | Date | Notes | 4 | |------------|-------------------| 5 | | 2020-06-02 | Initial release. | 6 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Microsoft Open Source Code of Conduct 2 | 3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 4 | 5 | Resources: 6 | 7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) 8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) 9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns 10 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | --- 2 | page_type: sample 3 | languages: 4 | - csharp 5 | products: 6 | - azure 7 | - azure-functions 8 | - azure-storage 9 | - azure-blob-storage 10 | - azure-bastion 11 | - azure-monitor 12 | - azure-cosmos-db 13 | - azure-dns 14 | - azure-private-link 15 | - azure-resource-manager 16 | - azure-virtual-machines-windows 17 | - azure-virtual-network 18 | - dotnet 19 | - vs-code 20 | description: "Sample showing how to connect Azure Functions to Azure resources using private endpoints." 21 | urlFragment: "connect-to-private-endpoints-with-azure-functions" 22 | azureDeploy: https://raw.githubusercontent.com/Azure-Samples/Azure-Functions-Private-Endpoints/master/template/azuredeploy.json?token=AAIW4AOWATWNQLL2JZKDBAK63EOOU 23 | --- 24 | 25 | # Connect to private endpoints with Azure Functions 26 | 27 | 34 | 35 | ![Build .NET Core](https://github.com/Azure-Samples/Azure-Functions-Private-Endpoints/workflows/.NET%20Core/badge.svg) 36 | 37 | This sample shows how Azure Functions can connect to other Azure resources via a [private endpoint](https://docs.microsoft.com/azure/private-link/private-endpoint-overview) connection. The sample uses an [Azure Functions Premium plan](https://docs.microsoft.com/azure/azure-functions/functions-premium-plan) with [regional VNet Integration](https://docs.microsoft.com/azure/azure-functions/functions-networking-options#regional-virtual-network-integration) to interact with Azure resources confined to a virtual network. 38 | 39 | ## Prerequisites 40 | 41 | The following components are required to run this sample: 42 | 43 | - [.NET Core 3.1](https://dotnet.microsoft.com/download/dotnet-core/3.1) 44 | - [Visual Studio Code](https://code.visualstudio.com/) 45 | - [Azure CLI](https://docs.microsoft.com/cli/azure/install-azure-cli?view=azure-cli-latest) 46 | - [Azure Functions Core Tools](https://docs.microsoft.com/azure/azure-functions/functions-run-local) 47 | - [Azure subscription](https://azure.microsoft.com/free/) 48 | 49 | ### Options 50 | 51 | You can use the [Azure Cosmos DB Emulator](https://docs.microsoft.com/azure/cosmos-db/local-emulator) and [Azure Storage Emulator](https://docs.microsoft.com/azure/storage/common/storage-use-emulator), along with the Azure Functions Core Tools, if you wish to develop and test locally. 52 | 53 | ## Deploy to Azure 54 | 55 | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure-Samples%2FAzure-Functions-Private-Endpoints%2Fmaster%2Ftemplate%2Fazuredeploy.json%3Ftoken%3DAAIW4AOWATWNQLL2JZKDBAK63EOOU) 56 | 57 | ### Deploy to Azure using the Azure CLI 58 | 59 | An alternative deployment approach is to use the Azure CLI to deploy the included Resource Manager template. 60 | 61 | ```azurecli 62 | az group create --name [YOUR-RESOURCE-GROUP-NAME] --location [YOUR-DESIRED-AZURE-REGION] 63 | 64 | az deployment group create -g [YOUR-RESOURCE-GROUP-NAME] --template-file azuredeploy.json --parameters azuredeploy.parameters.json 65 | ``` 66 | 67 | ### Deploy the Azure Function code 68 | 69 | After the Azure resources are deployed (which can take about 10-12 minutes), you will need to deploy the Azure Function to the newly created Azure Function app. You can use the [Azure Functions Core Tools to deploy the function](https://docs.microsoft.com/azure/azure-functions/functions-run-local?tabs=windows%2Ccsharp%2Cbash#publish). 70 | 71 | ```azurecli 72 | func azure functionapp publish [YOUR-FUNCTION-APP-NAME] 73 | ``` 74 | 75 | ## Running the sample 76 | 77 | Please perform the following steps to run the sample. 78 | 79 | 1. Connect to the newly created VM using Azure Bastion 80 | 2. Copy the `sample.csv` file to the newly created VM 81 | 3. From the VM, use a web browser to open the Azure portal. 82 | 4. Navigate to the newly created storage account which starts with `widgets`. Using Storage Explorer in the portal, upload the `sample.csv` file to the `orders` blob storage container. 83 | 5. Within a few seconds, the function's [blog trigger](https://docs.microsoft.com/azure/azure-functions/functions-bindings-storage-blob-trigger?tabs=csharp) should execute and process the file. 84 | 6. Navigate to newly created CosmosDB resource. Using Data Explorer in the portal, open the `Widgets` database and `Orders` collection. You should notice the same number of documents in the CosmosDB collection as were in the sample CSV file. 85 | 86 | ## Key concepts 87 | 88 | This sample demonstrates how to configure an Azure Function to work with Azure resources using private endpoints. By using private endpoints, the designated resources are accessible only via the virtual network. 89 | 90 | The sample sets up the following Azure resources: 91 | 92 | - Azure Function with blob trigger and CosmosDB output binding 93 | - Azure Function Premium plan with Virtual Network (VNet) Integration enabled 94 | - Virtual network 95 | - Configuring private endpoints for Azure resources 96 | - Azure Storage private endpoints 97 | - Azure Cosmos DB private endpoint 98 | - Private Azure DNS zones 99 | - Azure VM and Azure Bastion in order to access Azure resources within the virtual network. 100 | 101 | ### High level architecture 102 | 103 | The diagram provide shows a high-level depiction of the sample architecture. 104 | 105 | ![High level architecture diagram](./media/private-function-diagram.jpg) 106 | 107 | ### Storage accounts 108 | 109 | Azure Functions [requires the use of a general-purpose storage account](https://docs.microsoft.com/azure/azure-functions/storage-considerations#storage-account-requirements). This sample uses two storage accounts to meet that requirement. 110 | 111 | - The storage account referenced by the [AzureWebJobsStorage](https://docs.microsoft.com/azure/azure-functions/functions-app-settings#azurewebjobsstorage) application setting is configured with a private endpoint. 112 | - The storage account referenced by the [WEBSITE_CONTENTAZUREFILECONNECTIONSTRING](https://docs.microsoft.com/azure/azure-functions/functions-app-settings#website_contentazurefileconnectionstring) does not use a private endpoint. 113 | 114 | ### Access resources with VNet restrictions 115 | 116 | The sample provisions nearly all Azure resources within the confines of a virtual network. Attempts to access the following resources will only succeed from within the VM (which is itself within the virtual network) due to the virtual network restrictions on the resources: 117 | 118 | - Storage accounts 119 | - `widgets` + unique string (e.g. widgetspmobtiatsqdgc) 120 | - `fnapp` + unique string + `wjsa` (e.g.fnapppmobtiatsqdgcwjsa) 121 | - CosmosDB 122 | - `widgets` + unique string (e.g. widgetspmobtiatsqdgc) 123 | 124 | There are no virtual network restrictions on the following resources, and thus access to these resources is permitted from outside the virtual network (e.g. your desktop): 125 | 126 | - Storage accounts 127 | - `fnapp` + unique string (e.g. fnapppmobtiatsqdgcac) 128 | - `vmdiag` + unique string (e.g. vmdiagpmobtiatsqdgc) 129 | 130 | ## Contents 131 | 132 | Outline the file contents of the repository. It helps users navigate the codebase, build configuration and any related assets. 133 | 134 | | File/folder | Description | 135 | |-------------------|--------------------------------------------| 136 | | `.vscode` | VS Code related settings. | 137 | | `src` | Sample source code. | 138 | | `src\MyFunctions.cs` | Azure Function sample code. | 139 | | `src\sample.csv` | Sample CSV file. | 140 | | `template` | Azure Resource Manager template and deployment script. | 141 | | `template\azuredeploy.json` | Azure Resource Manager template for provisioning Azure resources. | 142 | | `template\azuredeploy.parameters.json` | Parameters used by the Azure Resource Manager template. | 143 | | `template\deploy.sh` | Script to deploy the template. | 144 | | `.gitignore` | Define what to ignore at commit time. | 145 | | `CHANGELOG.md` | List of changes to the sample. | 146 | | `CONTRIBUTING.md` | Guidelines for contributing to the sample. | 147 | | `README.md` | This README file. | 148 | | `LICENSE` | The license for the sample. | 149 | 150 | ## Contributing 151 | 152 | This project welcomes contributions and suggestions. Most contributions require you to agree to a 153 | Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us 154 | the rights to use your contribution. For details, visit [https://cla.opensource.microsoft.com](https://cla.opensource.microsoft.com). 155 | 156 | When you submit a pull request, a CLA bot will automatically determine whether you need to provide 157 | a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions 158 | provided by the bot. You will only need to do this once across all repos using our CLA. 159 | 160 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 161 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or 162 | contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 163 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Security 4 | 5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). 6 | 7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)), please report it to us as described below. 8 | 9 | ## Reporting Security Issues 10 | 11 | **Please do not report security vulnerabilities through public GitHub issues.** 12 | 13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). 14 | 15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). 16 | 17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). 18 | 19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: 20 | 21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) 22 | * Full paths of source file(s) related to the manifestation of the issue 23 | * The location of the affected source code (tag/branch/commit or direct URL) 24 | * Any special configuration required to reproduce the issue 25 | * Step-by-step instructions to reproduce the issue 26 | * Proof-of-concept or exploit code (if possible) 27 | * Impact of the issue, including how an attacker might exploit the issue 28 | 29 | This information will help us triage your report more quickly. 30 | 31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs. 32 | 33 | ## Preferred Languages 34 | 35 | We prefer all communications to be in English. 36 | 37 | ## Policy 38 | 39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd). 40 | 41 | -------------------------------------------------------------------------------- /media/private-function-diagram.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/Azure-Functions-Private-Endpoints/9f3e15627c2d292963b010a848083be5694b7d46/media/private-function-diagram.jpg -------------------------------------------------------------------------------- /src/OrderProcessingFunctions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | using Microsoft.Azure.WebJobs; 7 | using Microsoft.Extensions.Logging; 8 | 9 | using Newtonsoft.Json; 10 | 11 | using Newtonsoft.Json.Linq; 12 | 13 | 14 | namespace AzureSamples.AzureFunctionsPrivateEndpoints 15 | { 16 | public static class MyFunctions 17 | { 18 | [FunctionName("WidgetOrdersFunction")] 19 | public static async Task ProcessOrderDataFiles( 20 | [BlobTrigger("%ContainerName%/{blobName}", Connection = "WidgetsAzureStorageConnection")] Stream myBlobStream, 21 | string blobName, 22 | [CosmosDB( 23 | databaseName: "%CosmosDbName%", 24 | collectionName: "%CosmosDbCollectionName%", 25 | ConnectionStringSetting = "CosmosDBConnection")] IAsyncCollector items, 26 | ILogger logger) 27 | { 28 | logger.LogInformation($"C# Blob trigger function processed blob of name '{blobName}' with size of {myBlobStream.Length} bytes"); 29 | 30 | var jsonObject = await ConvertCsvToJsonAsync(myBlobStream); 31 | 32 | foreach (var item in jsonObject) 33 | { 34 | await items.AddAsync(JsonConvert.SerializeObject(item)); 35 | } 36 | } 37 | 38 | private static async Task> ConvertCsvToJsonAsync(Stream csvStream) 39 | { 40 | string[] header = { }; 41 | 42 | List jsonObjects = new List(); 43 | 44 | using (var streamReader = new StreamReader(csvStream)) 45 | { 46 | string line = null; 47 | 48 | while ((line = await streamReader.ReadLineAsync()) != null) 49 | { 50 | // Assume the first line contains the headers. 51 | if (header.Length == 0) 52 | { 53 | header = line.Split(',').Select(h => h.Trim()).ToArray(); 54 | } 55 | else 56 | { 57 | // Assume all other lines are data elements. 58 | 59 | // https://stackoverflow.com/a/50741265 60 | 61 | string[] lineItem = line.Split(',').Select(i => i.Trim()).ToArray(); 62 | var itemWithHeader = header.Zip(lineItem, (h, v) => new KeyValuePair(h, v)); 63 | var jsonItem = new JObject(itemWithHeader.Select(j => new JProperty(j.Key, j.Value))); 64 | 65 | jsonObjects.Add(jsonItem); 66 | } 67 | } 68 | } 69 | 70 | return jsonObjects; 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/host.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0", 3 | "logging": { 4 | "applicationInsights": { 5 | "samplingExcludedTypes": "Request", 6 | "samplingSettings": { 7 | "isEnabled": true 8 | } 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /src/private-endpoints.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | netcoreapp3.1 4 | v3 5 | func_vnet_storage 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | PreserveNewest 15 | 16 | 17 | PreserveNewest 18 | Never 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/sample.csv: -------------------------------------------------------------------------------- 1 | order_no, date, product_name, sku, quantity, price_ea 2 | 122, 07082020T21:45:13Z, shoes, 012457856, 1, 19.98 -------------------------------------------------------------------------------- /src/sample.local.settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "IsEncrypted": false, 3 | "Values": { 4 | "AzureWebJobsStorage": "UseDevelopmentStorage=true", 5 | "WidgetsAzureStorageConnection": "UseDevelopmentStorage=true", 6 | "FUNCTIONS_WORKER_RUNTIME": "dotnet", 7 | "ContainerName": "widget-orders", 8 | "CosmosDbName": "Widgets", 9 | "CosmosDbCollectionName": "orders", 10 | "CosmosDBConnection": "AccountEndpoint=https://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==" 11 | } 12 | } -------------------------------------------------------------------------------- /template/azuredeploy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "virtualMachineAdminUsername": { 6 | "type": "string" 7 | }, 8 | "virtualMachineAdminPassword": { 9 | "type": "securestring" 10 | }, 11 | "location": { 12 | "type": "string", 13 | "defaultValue": "[resourceGroup().location]" 14 | } 15 | }, 16 | "variables": { 17 | "virtualNetworkAddressPrefix": "10.100.0.0/16", 18 | "bastionSubnetAddressPrefix": "10.100.3.0/27", 19 | "virtualMachineSubnetAddressPrefix": "10.100.2.0/24", 20 | "functionSubnetAddressPrefix": "10.100.0.0/24", 21 | "privateEndpointSubnetAddressPrefix": "10.100.1.0/24", 22 | "functionAppName": "[concat('fnapp', uniqueString(resourceGroup().id))]", 23 | "hostingPlanName": "[concat(variables('functionAppName'), '-plan')]", 24 | "vnetName": "my-vnet", 25 | "functionWebJobsStorageAccountName": "[toLower(concat(variables('functionAppName'), 'wjsa'))]", 26 | "widgetOrdersStorageAccountName": "[toLower(concat('widgets', uniqueString(resourceGroup().id) ))]", 27 | "widgetOrdersBlobContainerName": "orders", 28 | "functionAppContentStorageAccountName": "[toLower(concat(variables('functionAppName'), 'ac'))]", 29 | "applicationInsightsName": "[concat(variables('functionAppName'), '-ai')]", 30 | "functionsSubnetName": "[concat(variables('vnetName'), '-functions')]", 31 | "privateEndpointSubnetName": "[concat(variables('vnetName'), '-privateendpoint')]", 32 | "privateEndpointStorageBlobName": "widgets-blob-private-endpoint", 33 | "privateEndpointCosmosDbName": "[concat(variables('cosmosDbAccountName'), '-private-endpoint')]", 34 | "privateEndpointWebJobsQueueStorageName": "[concat(variables('functionWebJobsStorageAccountName'), '-queue-private-endpoint')]", 35 | "privateEndpointWebJobsTableStorageName": "[concat(variables('functionWebJobsStorageAccountName'), '-table-private-endpoint')]", 36 | "privateEndpointWebJobsBlobStorageName": "[concat(variables('functionWebJobsStorageAccountName'), '-blob-private-endpoint')]", 37 | "privateEndpointWebJobsFileStorageName": "[concat(variables('functionWebJobsStorageAccountName'), '-file-private-endpoint')]", 38 | "privateStorageQueueDnsZoneName": "privatelink.queue.core.windows.net", 39 | "privateStorageBlobDnsZoneName": "privatelink.blob.core.windows.net", 40 | "privateStorageTableDnsZoneName": "privatelink.table.core.windows.net", 41 | "privateStorageFileDnsZoneName": "privatelink.file.core.windows.net", 42 | "privateCosmosDbDnsZoneName": "privatelink.documents.azure.com", 43 | "vmDiagnosticStorageAccountName": "[concat('vmdiag', uniqueString(resourceGroup().id))]", 44 | "virtualMachineName": "my-vm", 45 | "vmNicName": "[concat(variables('virtualMachineName'), '-nic')]", 46 | "vmSubnetName": "[concat(variables('vnetName'), '-vm')]", 47 | "vmNsgName": "[concat(variables('virtualMachineName'), '-nsg')]", 48 | "cosmosDbAccountName": "[concat('widgets', uniqueString(resourceGroup().id))]", 49 | "cosmosDbDatabaseName": "Widgets", 50 | "cosmosDbContainerName": "Orders", 51 | "bastionPublicIPAddressName": "bastion-pip", 52 | "dnsLabelPrefix": "[concat('vm', uniqueString(resourceGroup().id))]", 53 | "bastionHostName": "bastion-host", 54 | "bastionSubnetName": "AzureBastionSubnet", 55 | "appInsightsResourceId": "[resourceId('Microsoft.Insights/components', variables('applicationInsightsName'))]" 56 | }, 57 | "resources": [ 58 | { 59 | "type": "Microsoft.Network/virtualNetworks", 60 | "apiVersion": "2019-11-01", 61 | "location": "[parameters('location')]", 62 | "name": "[variables('vnetName')]", 63 | "dependsOn": [ 64 | "[resourceId('Microsoft.Network/networkSecurityGroups/', variables('vmNsgName'))]" 65 | ], 66 | "properties": { 67 | "addressSpace": { 68 | "addressPrefixes": [ 69 | "[variables('virtualNetworkAddressPrefix')]" 70 | ] 71 | }, 72 | "subnets": [ 73 | { 74 | "name": "[variables('functionsSubnetName')]", 75 | "properties": { 76 | "addressPrefix": "[variables('functionSubnetAddressPrefix')]", 77 | "privateEndpointNetworkPolicies": "Enabled", 78 | "privateLinkServiceNetworkPolicies": "Enabled", 79 | "delegations": [ 80 | { 81 | "name": "webapp", 82 | "properties": { 83 | "serviceName": "Microsoft.Web/serverFarms", 84 | "actions": [ 85 | "Microsoft.Network/virtualNetworks/subnets/action" 86 | ] 87 | } 88 | } 89 | ] 90 | } 91 | }, 92 | { 93 | "name": "[variables('privateEndpointSubnetName')]", 94 | "properties": { 95 | "addressPrefix": "[variables('privateEndpointSubnetAddressPrefix')]", 96 | "privateLinkServiceNetworkPolicies": "Enabled", 97 | "privateEndpointNetworkPolicies": "Disabled" 98 | } 99 | }, 100 | { 101 | "name": "[variables('vmSubnetName')]", 102 | "properties": { 103 | "addressPrefix": "[variables('virtualMachineSubnetAddressPrefix')]", 104 | "networkSecurityGroup": { 105 | "id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('vmNsgName'))]" 106 | }, 107 | "privateLinkServiceNetworkPolicies": "Enabled", 108 | "privateEndpointNetworkPolicies": "Disabled" 109 | } 110 | }, 111 | { 112 | "name": "[variables('bastionSubnetName')]", 113 | "properties": { 114 | "addressPrefix": "[variables('bastionSubnetAddressPrefix')]", 115 | "privateEndpointNetworkPolicies": "Enabled", 116 | "privateLinkServiceNetworkPolicies": "Enabled" 117 | } 118 | } 119 | ] 120 | } 121 | }, 122 | { 123 | "type": "Microsoft.Storage/storageAccounts", 124 | "apiVersion": "2019-06-01", 125 | "location": "[parameters('location')]", 126 | "name": "[variables('functionAppContentStorageAccountName')]", 127 | "sku": { 128 | "name": "Standard_LRS", 129 | "tier": "Standard" 130 | }, 131 | "kind": "StorageV2", 132 | "properties": { 133 | "networkAcls": { 134 | "bypass": "AzureServices", 135 | "defaultAction": "Allow" 136 | }, 137 | "supportsHttpsTrafficOnly": true 138 | } 139 | }, 140 | { 141 | "type": "Microsoft.Storage/storageAccounts", 142 | "apiVersion": "2019-06-01", 143 | "location": "[parameters('location')]", 144 | "name": "[variables('widgetOrdersStorageAccountName')]", 145 | "sku": { 146 | "name": "Standard_LRS", 147 | "tier": "Standard" 148 | }, 149 | "kind": "StorageV2", 150 | "properties": { 151 | "networkAcls": { 152 | "bypass": "AzureServices", 153 | "defaultAction": "Deny" 154 | }, 155 | "supportsHttpsTrafficOnly": true 156 | }, 157 | "resources": [ 158 | { 159 | "name": "[concat('default/', variables('widgetOrdersBlobContainerName'))]", 160 | "type": "blobServices/containers", 161 | "apiVersion": "2018-07-01", 162 | "dependsOn": [ 163 | "[variables('widgetOrdersStorageAccountName')]" 164 | ] 165 | } 166 | ] 167 | }, 168 | { 169 | "type": "Microsoft.Storage/storageAccounts", 170 | "apiVersion": "2019-06-01", 171 | "location": "[parameters('location')]", 172 | "dependsOn": [ 173 | "[resourceId('Microsoft.Network/virtualNetworks', variables('vnetName'))]" 174 | ], 175 | "name": "[variables('functionWebJobsStorageAccountName')]", 176 | "sku": { 177 | "name": "Standard_LRS", 178 | "tier": "Standard" 179 | }, 180 | "kind": "StorageV2", 181 | "properties": { 182 | "networkAcls": { 183 | "bypass": "AzureServices", 184 | "defaultAction": "Deny" 185 | }, 186 | "supportsHttpsTrafficOnly": true 187 | } 188 | }, 189 | { 190 | "type": "Microsoft.Storage/storageAccounts", 191 | "apiVersion": "2019-04-01", 192 | "name": "[variables('vmDiagnosticStorageAccountName')]", 193 | "location": "[parameters('location')]", 194 | "sku": { 195 | "name": "Standard_LRS" 196 | }, 197 | "kind": "Storage", 198 | "properties": { 199 | } 200 | }, 201 | { 202 | "type": "Microsoft.DocumentDB/databaseAccounts", 203 | "name": "[variables('cosmosDbAccountName')]", 204 | "apiVersion": "2020-03-01", 205 | "kind": "GlobalDocumentDB", 206 | "location": "[parameters('location')]", 207 | "properties": { 208 | "consistencyPolicy": { 209 | "Session": { 210 | "defaultConsistencyLevel": "Session" 211 | } 212 | }, 213 | "locations": [ 214 | { 215 | "locationName": "[parameters('location')]", 216 | "failoverPriority": 0, 217 | "isZoneRedundant": false 218 | } 219 | ], 220 | "databaseAccountOfferType": "Standard", 221 | "publicNetworkAccess": "Disabled" 222 | } 223 | }, 224 | { 225 | "type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases", 226 | "name": "[concat(variables('cosmosDbAccountName'), '/', variables('cosmosDbDatabaseName'))]", 227 | "apiVersion": "2019-08-01", 228 | "dependsOn": [ 229 | "[resourceId('Microsoft.DocumentDB/databaseAccounts', variables('cosmosDbAccountName'))]" 230 | ], 231 | "properties": { 232 | "resource": { 233 | "id": "[ variables('cosmosDbDatabaseName')]" 234 | }, 235 | "options": { 236 | } 237 | } 238 | }, 239 | { 240 | "type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers", 241 | "name": "[concat(variables('cosmosDbAccountName'), '/', variables('cosmosDbDatabaseName'), '/', variables('cosmosDbContainerName'))]", 242 | "apiVersion": "2019-08-01", 243 | "dependsOn": [ 244 | "[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases', variables('cosmosDbAccountName'), variables('cosmosDbDatabaseName'))]", 245 | "[resourceId('Microsoft.DocumentDB/databaseAccounts', variables('cosmosDbAccountName'))]" 246 | ], 247 | "properties": { 248 | "resource": { 249 | "id": "[variables('cosmosDbContainerName')]", 250 | "partitionKey": { 251 | "paths": [ 252 | "/id" 253 | ], 254 | "kind": "Hash" 255 | }, 256 | "indexingPolicy": { 257 | "indexingMode": "consistent", 258 | "includedPaths": [ 259 | { 260 | "path": "/*" 261 | } 262 | ], 263 | "excludedPaths": [ 264 | { 265 | "path": "/\"_etag\"/?" 266 | } 267 | ] 268 | } 269 | }, 270 | "options": { 271 | "throughput": 400 272 | } 273 | } 274 | }, 275 | { 276 | "type": "Microsoft.Compute/virtualMachines", 277 | "apiVersion": "2019-03-01", 278 | "name": "[variables('virtualMachineName')]", 279 | "location": "[parameters('location')]", 280 | "dependsOn": [ 281 | "[resourceId('Microsoft.Storage/storageAccounts/', variables('vmDiagnosticStorageAccountName'))]", 282 | "[resourceId('Microsoft.Network/networkInterfaces/', variables('vmNicName'))]" 283 | ], 284 | "properties": { 285 | "hardwareProfile": { 286 | "vmSize": "Standard_D2_v3" 287 | }, 288 | "osProfile": { 289 | "computerName": "[variables('virtualMachineName')]", 290 | "adminUsername": "[parameters('virtualMachineAdminUsername')]", 291 | "adminPassword": "[parameters('virtualMachineAdminPassword')]" 292 | }, 293 | "storageProfile": { 294 | "imageReference": { 295 | "publisher": "MicrosoftWindowsDesktop", 296 | "offer": "Windows-10", 297 | "sku": "rs5-pro", 298 | "version": "latest" 299 | }, 300 | "osDisk": { 301 | "createOption": "FromImage" 302 | } 303 | }, 304 | "networkProfile": { 305 | "networkInterfaces": [ 306 | { 307 | "id": "[resourceId('Microsoft.Nework/networkInterfaces', variables('vmNicName'))]" 308 | } 309 | ] 310 | }, 311 | "diagnosticsProfile": { 312 | "bootDiagnostics": { 313 | "enabled": true, 314 | "storageUri": "[reference(resourceId('Microsoft.Storage/storageAccounts/', variables('vmDiagnosticStorageAccountName'))).primaryEndpoints.blob]" 315 | } 316 | } 317 | } 318 | }, 319 | { 320 | "type": "Microsoft.DevTestLab/schedules", 321 | "name": "[concat('shutdown-computevm-', variables('virtualMachineName'))]", 322 | "apiVersion": "2018-09-15", 323 | "location": "[parameters('location')]", 324 | "dependsOn": [ 325 | "[concat('Microsoft.Compute/virtualMachines/', variables('virtualMachineName'))]" 326 | ], 327 | "properties": { 328 | "status": "Enabled", 329 | "taskType": "ComputeVmShutdownTask", 330 | "dailyRecurrence": { 331 | "time": "1900" 332 | }, 333 | "timeZoneId": "UTC", 334 | "notificationSettings": { 335 | "status": "Disabled" 336 | }, 337 | "targetResourceId": "[resourceId('Microsoft.Compute/virtualMachines',variables('virtualMachineName'))]" 338 | } 339 | }, 340 | { 341 | "type": "Microsoft.Insights/components", 342 | "apiVersion": "2015-05-01", 343 | "location": "[parameters('location')]", 344 | "name": "[variables('applicationInsightsName')]", 345 | "kind": "web", 346 | "properties": { 347 | "Application_Type": "web", 348 | "ApplicationId": "[variables('applicationInsightsName')]" 349 | } 350 | }, 351 | { 352 | "type": "Microsoft.Network/privateDnsZones", 353 | "apiVersion": "2018-09-01", 354 | "name": "[variables('privateStorageQueueDnsZoneName')]", 355 | "location": "global", 356 | "properties": "" 357 | }, 358 | { 359 | "type": "Microsoft.Network/privateDnsZones", 360 | "apiVersion": "2018-09-01", 361 | "name": "[variables('privateStorageBlobDnsZoneName')]", 362 | "location": "global", 363 | "properties": "" 364 | }, 365 | { 366 | "type": "Microsoft.Network/privateDnsZones", 367 | "apiVersion": "2018-09-01", 368 | "name": "[variables('privateStorageTableDnsZoneName')]", 369 | "location": "global", 370 | "properties": "" 371 | }, 372 | { 373 | "type": "Microsoft.Network/privateDnsZones", 374 | "apiVersion": "2018-09-01", 375 | "name": "[variables('privateStorageFileDnsZoneName')]", 376 | "location": "global", 377 | "properties": "" 378 | }, 379 | { 380 | "type": "Microsoft.Network/privateDnsZones", 381 | "apiVersion": "2018-09-01", 382 | "name": "[variables('privateCosmosDbDnsZoneName')]", 383 | "location": "global", 384 | "properties": "" 385 | }, 386 | { 387 | "type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks", 388 | "apiVersion": "2018-09-01", 389 | "name": "[concat(variables('privateStorageQueueDnsZoneName'), '/', variables('privateStorageQueueDnsZoneName'), '-link')]", 390 | "location": "global", 391 | "dependsOn": [ 392 | "[resourceId('Microsoft.Network/privateDnsZones', variables('privateStorageQueueDnsZoneName'))]", 393 | "[resourceId('Microsoft.Network/virtualNetworks', variables('vnetName'))]" 394 | ], 395 | "properties": { 396 | "registrationEnabled": false, 397 | "virtualNetwork": { 398 | "id": "[resourceId('Microsoft.Network/virtualNetworks', variables('vnetName'))]" 399 | } 400 | } 401 | }, 402 | { 403 | "type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks", 404 | "apiVersion": "2018-09-01", 405 | "name": "[concat(variables('privateStorageTableDnsZoneName'), '/', variables('privateStorageTableDnsZoneName'), '-link')]", 406 | "location": "global", 407 | "dependsOn": [ 408 | "[resourceId('Microsoft.Network/privateDnsZones', variables('privateStorageTableDnsZoneName'))]", 409 | "[resourceId('Microsoft.Network/virtualNetworks', variables('vnetName'))]" 410 | ], 411 | "properties": { 412 | "registrationEnabled": false, 413 | "virtualNetwork": { 414 | "id": "[resourceId('Microsoft.Network/virtualNetworks', variables('vnetName'))]" 415 | } 416 | } 417 | }, 418 | { 419 | "type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks", 420 | "apiVersion": "2018-09-01", 421 | "name": "[concat(variables('privateStorageBlobDnsZoneName'), '/', variables('privateStorageBlobDnsZoneName'), '-link')]", 422 | "location": "global", 423 | "dependsOn": [ 424 | "[resourceId('Microsoft.Network/privateDnsZones', variables('privateStorageBlobDnsZoneName'))]", 425 | "[resourceId('Microsoft.Network/virtualNetworks', variables('vnetName'))]" 426 | ], 427 | "properties": { 428 | "registrationEnabled": false, 429 | "virtualNetwork": { 430 | "id": "[resourceId('Microsoft.Network/virtualNetworks', variables('vnetName'))]" 431 | } 432 | } 433 | }, 434 | { 435 | "type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks", 436 | "apiVersion": "2018-09-01", 437 | "name": "[concat(variables('privateStorageFileDnsZoneName'), '/', variables('privateStorageFileDnsZoneName'), '-link')]", 438 | "location": "global", 439 | "dependsOn": [ 440 | "[resourceId('Microsoft.Network/privateDnsZones', variables('privateStorageFileDnsZoneName'))]", 441 | "[resourceId('Microsoft.Network/virtualNetworks', variables('vnetName'))]" 442 | ], 443 | "properties": { 444 | "registrationEnabled": false, 445 | "virtualNetwork": { 446 | "id": "[resourceId('Microsoft.Network/virtualNetworks', variables('vnetName'))]" 447 | } 448 | } 449 | }, 450 | { 451 | "type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks", 452 | "apiVersion": "2018-09-01", 453 | "name": "[concat(variables('privateCosmosDbDnsZoneName'), '/', variables('privateCosmosDbDnsZoneName'), '-link')]", 454 | "location": "global", 455 | "dependsOn": [ 456 | "[resourceId('Microsoft.Network/privateDnsZones', variables('privateCosmosDbDnsZoneName'))]", 457 | "[resourceId('Microsoft.Network/virtualNetworks', variables('vnetName'))]" 458 | ], 459 | "properties": { 460 | "registrationEnabled": false, 461 | "virtualNetwork": { 462 | "id": "[resourceId('Microsoft.Network/virtualNetworks', variables('vnetName'))]" 463 | } 464 | } 465 | }, 466 | { 467 | "type": "Microsoft.Network/privateEndpoints", 468 | "name": "[variables('privateEndpointStorageBlobName')]", 469 | "apiVersion": "2019-11-01", 470 | "location": "[parameters('location')]", 471 | "dependsOn": [ 472 | "[resourceId('Microsoft.Storage/storageAccounts', variables('widgetOrdersStorageAccountName'))]", 473 | "[resourceId('Microsoft.Network/virtualNetworks', variables('vnetName'))]" 474 | ], 475 | "properties": { 476 | "subnet": { 477 | "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('vnetName'), variables('privateEndpointSubnetName') )]" 478 | }, 479 | "privateLinkServiceConnections": [ 480 | { 481 | "name": "MyStorageBlobPrivateLinkConnection", 482 | "properties": { 483 | "privateLinkServiceId": "[resourceId('Microsoft.Storage/storageAccounts', variables('widgetOrdersStorageAccountName'))]", 484 | "groupIds": [ 485 | "blob" 486 | ] 487 | } 488 | } 489 | ] 490 | } 491 | }, 492 | { 493 | "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", 494 | "apiVersion": "2020-03-01", 495 | "location": "[parameters('location')]", 496 | "name": "[concat(variables('privateEndpointStorageBlobName'), '/default')]", 497 | "dependsOn": [ 498 | "[resourceId('Microsoft.Network/privateDnsZones', variables('privateStorageBlobDnsZoneName'))]", 499 | "[resourceId('Microsoft.Network/privateEndpoints', variables('privateEndpointStorageBlobName'))]" 500 | ], 501 | "properties": { 502 | "privateDnsZoneConfigs": [ 503 | { 504 | "name": "config1", 505 | "properties": { 506 | "privateDnsZoneId": "[resourceId('Microsoft.Network/privateDnsZones', variables('privateStorageBlobDnsZoneName'))]" 507 | } 508 | } 509 | ] 510 | } 511 | }, 512 | { 513 | "type": "Microsoft.Network/privateEndpoints", 514 | "name": "[variables('privateEndpointWebJobsQueueStorageName')]", 515 | "apiVersion": "2019-11-01", 516 | "location": "[parameters('location')]", 517 | "dependsOn": [ 518 | "[resourceId('Microsoft.Storage/storageAccounts', variables('functionWebJobsStorageAccountName'))]", 519 | "[resourceId('Microsoft.Network/virtualNetworks', variables('vnetName'))]" 520 | ], 521 | "properties": { 522 | "subnet": { 523 | "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('vnetName'), variables('privateEndpointSubnetName') )]" 524 | }, 525 | "privateLinkServiceConnections": [ 526 | { 527 | "name": "MyStorageQueuePrivateLinkConnection", 528 | "properties": { 529 | "privateLinkServiceId": "[resourceId('Microsoft.Storage/storageAccounts', variables('functionWebJobsStorageAccountName'))]", 530 | "groupIds": [ 531 | "queue" 532 | ] 533 | } 534 | } 535 | ] 536 | } 537 | }, 538 | { 539 | "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", 540 | "apiVersion": "2020-03-01", 541 | "location": "[parameters('location')]", 542 | "name": "[concat(variables('privateEndpointWebJobsQueueStorageName'), '/default')]", 543 | "dependsOn": [ 544 | "[resourceId('Microsoft.Network/privateDnsZones', variables('privateStorageQueueDnsZoneName'))]", 545 | "[resourceId('Microsoft.Network/privateEndpoints', variables('privateEndpointWebJobsQueueStorageName'))]" 546 | ], 547 | "properties": { 548 | "privateDnsZoneConfigs": [ 549 | { 550 | "name": "config1", 551 | "properties": { 552 | "privateDnsZoneId": "[resourceId('Microsoft.Network/privateDnsZones', variables('privateStorageQueueDnsZoneName'))]" 553 | } 554 | } 555 | ] 556 | } 557 | }, 558 | { 559 | "type": "Microsoft.Network/privateEndpoints", 560 | "name": "[variables('privateEndpointWebJobsTableStorageName')]", 561 | "apiVersion": "2019-11-01", 562 | "location": "[parameters('location')]", 563 | "dependsOn": [ 564 | "[resourceId('Microsoft.Storage/storageAccounts', variables('functionWebJobsStorageAccountName'))]", 565 | "[resourceId('Microsoft.Network/virtualNetworks', variables('vnetName'))]" 566 | ], 567 | "properties": { 568 | "subnet": { 569 | "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('vnetName'), variables('privateEndpointSubnetName') )]" 570 | }, 571 | "privateLinkServiceConnections": [ 572 | { 573 | "name": "MyStorageQueuePrivateLinkConnection", 574 | "properties": { 575 | "privateLinkServiceId": "[resourceId('Microsoft.Storage/storageAccounts', variables('functionWebJobsStorageAccountName'))]", 576 | "groupIds": [ 577 | "table" 578 | ] 579 | } 580 | } 581 | ] 582 | } 583 | }, 584 | { 585 | "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", 586 | "apiVersion": "2020-03-01", 587 | "location": "[parameters('location')]", 588 | "name": "[concat(variables('privateEndpointWebJobsTableStorageName'), '/default')]", 589 | "dependsOn": [ 590 | "[resourceId('Microsoft.Network/privateDnsZones', variables('privateStorageTableDnsZoneName'))]", 591 | "[resourceId('Microsoft.Network/privateEndpoints', variables('privateEndpointWebJobsTableStorageName'))]" 592 | ], 593 | "properties": { 594 | "privateDnsZoneConfigs": [ 595 | { 596 | "name": "config1", 597 | "properties": { 598 | "privateDnsZoneId": "[resourceId('Microsoft.Network/privateDnsZones', variables('privateStorageTableDnsZoneName'))]" 599 | } 600 | } 601 | ] 602 | } 603 | }, 604 | { 605 | "type": "Microsoft.Network/privateEndpoints", 606 | "name": "[variables('privateEndpointWebJobsBlobStorageName')]", 607 | "apiVersion": "2019-11-01", 608 | "location": "[parameters('location')]", 609 | "dependsOn": [ 610 | "[resourceId('Microsoft.Storage/storageAccounts', variables('functionWebJobsStorageAccountName'))]", 611 | "[resourceId('Microsoft.Network/virtualNetworks', variables('vnetName'))]" 612 | ], 613 | "properties": { 614 | "subnet": { 615 | "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('vnetName'), variables('privateEndpointSubnetName') )]" 616 | }, 617 | "privateLinkServiceConnections": [ 618 | { 619 | "name": "MyStorageQueuePrivateLinkConnection", 620 | "properties": { 621 | "privateLinkServiceId": "[resourceId('Microsoft.Storage/storageAccounts', variables('functionWebJobsStorageAccountName'))]", 622 | "groupIds": [ 623 | "blob" 624 | ] 625 | } 626 | } 627 | ] 628 | } 629 | }, 630 | { 631 | "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", 632 | "apiVersion": "2020-03-01", 633 | "location": "[parameters('location')]", 634 | "name": "[concat(variables('privateEndpointWebJobsBlobStorageName'), '/default')]", 635 | "dependsOn": [ 636 | "[resourceId('Microsoft.Network/privateDnsZones', variables('privateStorageBlobDnsZoneName'))]", 637 | "[resourceId('Microsoft.Network/privateEndpoints', variables('privateEndpointWebJobsBlobStorageName'))]" 638 | ], 639 | "properties": { 640 | "privateDnsZoneConfigs": [ 641 | { 642 | "name": "config1", 643 | "properties": { 644 | "privateDnsZoneId": "[resourceId('Microsoft.Network/privateDnsZones', variables('privateStorageBlobDnsZoneName'))]" 645 | } 646 | } 647 | ] 648 | } 649 | }, 650 | { 651 | "type": "Microsoft.Network/privateEndpoints", 652 | "name": "[variables('privateEndpointWebJobsFileStorageName')]", 653 | "apiVersion": "2019-11-01", 654 | "location": "[parameters('location')]", 655 | "dependsOn": [ 656 | "[resourceId('Microsoft.Storage/storageAccounts', variables('functionWebJobsStorageAccountName'))]", 657 | "[resourceId('Microsoft.Network/virtualNetworks', variables('vnetName'))]" 658 | ], 659 | "properties": { 660 | "subnet": { 661 | "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('vnetName'), variables('privateEndpointSubnetName') )]" 662 | }, 663 | "privateLinkServiceConnections": [ 664 | { 665 | "name": "MyStorageQueuePrivateLinkConnection", 666 | "properties": { 667 | "privateLinkServiceId": "[resourceId('Microsoft.Storage/storageAccounts', variables('functionWebJobsStorageAccountName'))]", 668 | "groupIds": [ 669 | "file" 670 | ] 671 | } 672 | } 673 | ] 674 | } 675 | }, 676 | { 677 | "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", 678 | "apiVersion": "2020-03-01", 679 | "location": "[parameters('location')]", 680 | "name": "[concat(variables('privateEndpointWebJobsFileStorageName'), '/default')]", 681 | "dependsOn": [ 682 | "[resourceId('Microsoft.Network/privateDnsZones', variables('privateStorageFileDnsZoneName'))]", 683 | "[resourceId('Microsoft.Network/privateEndpoints', variables('privateEndpointWebJobsFileStorageName'))]" 684 | ], 685 | "properties": { 686 | "privateDnsZoneConfigs": [ 687 | { 688 | "name": "config1", 689 | "properties": { 690 | "privateDnsZoneId": "[resourceId('Microsoft.Network/privateDnsZones', variables('privateStorageFileDnsZoneName'))]" 691 | } 692 | } 693 | ] 694 | } 695 | }, 696 | { 697 | "type": "Microsoft.Network/privateEndpoints", 698 | "name": "[variables('privateEndpointCosmosDbName')]", 699 | "apiVersion": "2019-11-01", 700 | "location": "[parameters('location')]", 701 | "dependsOn": [ 702 | "[resourceId('Microsoft.DocumentDB/databaseAccounts', variables('cosmosDbAccountName'))]", 703 | "[resourceId('Microsoft.Network/virtualNetworks', variables('vnetName'))]" 704 | ], 705 | "properties": { 706 | "subnet": { 707 | "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('vnetName'), variables('privateEndpointSubnetName') )]" 708 | }, 709 | "privateLinkServiceConnections": [ 710 | { 711 | "name": "MyCosmosDbPrivateLinkConnection", 712 | "properties": { 713 | "privateLinkServiceId": "[resourceId('Microsoft.DocumentDB/databaseAccounts', variables('cosmosDbAccountName'))]", 714 | "groupIds": [ 715 | "Sql" 716 | ] 717 | } 718 | } 719 | ] 720 | } 721 | }, 722 | { 723 | "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", 724 | "apiVersion": "2020-03-01", 725 | "location": "[parameters('location')]", 726 | "name": "[concat(variables('privateEndpointCosmosDbName'), '/default')]", 727 | "dependsOn": [ 728 | "[resourceId('Microsoft.Network/privateDnsZones', variables('privateCosmosDbDnsZoneName'))]", 729 | "[resourceId('Microsoft.Network/privateEndpoints', variables('privateEndpointCosmosDbName'))]" 730 | ], 731 | "properties": { 732 | "privateDnsZoneConfigs": [ 733 | { 734 | "name": "config1", 735 | "properties": { 736 | "privateDnsZoneId": "[resourceId('Microsoft.Network/privateDnsZones', variables('privateCosmosDbDnsZoneName'))]" 737 | } 738 | } 739 | ] 740 | } 741 | }, 742 | { 743 | "type": "Microsoft.Network/bastionHosts", 744 | "name": "[variables('bastionHostName')]", 745 | "apiVersion": "2019-11-01", 746 | "location": "[parameters('location')]", 747 | "dependsOn": [ 748 | "[resourceId('Microsoft.Network/publicIpAddresses', variables('bastionPublicIPAddressName'))]", 749 | "[resourceId('Microsoft.Network/virtualNetworks', variables('vnetName'))]" 750 | ], 751 | "properties": { 752 | "ipConfigurations": [ 753 | { 754 | "name": "IpConf", 755 | "properties": { 756 | "subnet": { 757 | "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('vnetName'), variables('BastionSubnetName'))]" 758 | }, 759 | "publicIPAddress": { 760 | "id": "[resourceId('Microsoft.Network/publicIpAddresses', variables('bastionPublicIPAddressName'))]" 761 | } 762 | } 763 | } 764 | ] 765 | } 766 | }, 767 | { 768 | "type": "Microsoft.Network/networkInterfaces", 769 | "apiVersion": "2018-11-01", 770 | "name": "[variables('vmNicName')]", 771 | "location": "[parameters('location')]", 772 | "dependsOn": [ 773 | "[resourceId('Microsoft.Network/virtualNetworks/', variables('vnetName'))]" 774 | ], 775 | "properties": { 776 | "ipConfigurations": [ 777 | { 778 | "name": "ipconfig1", 779 | "properties": { 780 | "privateIPAllocationMethod": "Dynamic", 781 | "subnet": { 782 | "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('vnetName'), variables('vmSubnetName'))]" 783 | } 784 | } 785 | } 786 | ] 787 | } 788 | }, 789 | { 790 | "type": "Microsoft.Network/publicIPAddresses", 791 | "apiVersion": "2018-11-01", 792 | "name": "[variables('bastionPublicIPAddressName')]", 793 | "location": "[parameters('location')]", 794 | "sku": { 795 | "name": "Standard" 796 | }, 797 | "properties": { 798 | "publicIPAllocationMethod": "Static", 799 | "dnsSettings": { 800 | "domainNameLabel": "[variables('dnsLabelPrefix')]" 801 | } 802 | } 803 | }, 804 | { 805 | "apiVersion": "2019-04-01", 806 | "type": "Microsoft.Network/networkSecurityGroups", 807 | "name": "[variables('vmNsgName')]", 808 | "location": "[parameters('location')]", 809 | "properties": { 810 | "securityRules": [ 811 | { 812 | "name": "Block_RDP_Internet", 813 | "properties": { 814 | "description": "Block RDP", 815 | "protocol": "Tcp", 816 | "sourcePortRange": "*", 817 | "destinationPortRange": "3389", 818 | "sourceAddressPrefix": "Internet", 819 | "destinationAddressPrefix": "*", 820 | "access": "Deny", 821 | "priority": 101, 822 | "direction": "Inbound" 823 | } 824 | } 825 | ] 826 | } 827 | }, 828 | { 829 | "type": "Microsoft.Web/serverfarms", 830 | "apiVersion": "2018-02-01", 831 | "name": "[variables('hostingPlanName')]", 832 | "location": "[parameters('location')]", 833 | "sku": { 834 | "name": "EP1", 835 | "tier": "ElasticPremium" 836 | }, 837 | "kind": "elastic", 838 | "properties": { 839 | "maximumElasticWorkerCount": 20 840 | } 841 | }, 842 | { 843 | "type": "Microsoft.Web/sites", 844 | "apiVersion": "2018-11-01", 845 | "name": "[variables('functionAppName')]", 846 | "location": "[parameters('location')]", 847 | "dependsOn": [ 848 | "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]", 849 | "[resourceId('Microsoft.Storage/storageAccounts', variables('functionWebJobsStorageAccountName'))]", 850 | "[resourceId('Microsoft.Storage/storageAccounts', variables('functionAppContentStorageAccountName'))]", 851 | "[resourceId('Microsoft.Network/virtualNetworks', variables('vnetName'))]" 852 | ], 853 | "kind": "functionapp", 854 | "properties": { 855 | "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]", 856 | "siteConfig": { 857 | "appSettings": [ 858 | { 859 | "name": "APPINSIGHTS_INSTRUMENTATIONKEY", 860 | "value": "[reference(variables('appInsightsResourceId'), '2018-05-01-preview').instrumentationKey]" 861 | }, 862 | { 863 | "name": "APPLICATIONINSIGHTS_CONNECTION_STRING", 864 | "value": "[concat('InstrumentationKey=', reference(variables('appInsightsResourceId'), '2018-05-01-preview').instrumentationKey)]" 865 | }, 866 | { 867 | "name": "AzureWebJobsStorage", 868 | "value": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('functionWebJobsStorageAccountName'),';AccountKey=',listkeys(resourceId('Microsoft.Storage/storageAccounts', variables('functionWebJobsStorageAccountName')), '2018-11-01').keys[0].value,';')]" 869 | }, 870 | { 871 | "name": "FUNCTIONS_EXTENSION_VERSION", 872 | "value": "~3" 873 | }, 874 | { 875 | "name": "FUNCTIONS_WORKER_RUNTIME", 876 | "value": "dotnet" 877 | }, 878 | { 879 | "name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING", 880 | "value": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('functionAppContentStorageAccountName'),';AccountKey=',listkeys(resourceId('Microsoft.Storage/storageAccounts', variables('functionAppContentStorageAccountName')), '2018-11-01').keys[0].value,';')]" 881 | }, 882 | { 883 | "name": "WEBSITE_CONTENTSHARE", 884 | "value": "[toLower(variables('hostingPlanName'))]" 885 | }, 886 | { 887 | "name": "WEBSITE_NODE_DEFAULT_VERSION", 888 | "value": "~12" 889 | }, 890 | { 891 | "name": "WEBSITE_VNET_ROUTE_ALL", 892 | "value": "1" 893 | }, 894 | { 895 | "name": "WEBSITE_DNS_SERVER", 896 | "value": "168.63.129.16" 897 | }, 898 | { 899 | "name": "WidgetsAzureStorageConnection", 900 | "value": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('widgetOrdersStorageAccountName'),';AccountKey=',listkeys(resourceId('Microsoft.Storage/storageAccounts', variables('widgetOrdersStorageAccountName')), '2018-11-01').keys[0].value,';')]" 901 | }, 902 | { 903 | "name": "ContainerName", 904 | "value": "[variables('widgetOrdersBlobContainerName')]" 905 | }, 906 | { 907 | "name": "CosmosDbName", 908 | "value": "[variables('cosmosDbDatabaseName')]" 909 | }, 910 | { 911 | "name": "CosmosDbCollectionName", 912 | "value": "[variables('cosmosDbContainerName')]" 913 | }, 914 | { 915 | "name": "CosmosDBConnection", 916 | "value": "[listConnectionStrings(resourceId('Microsoft.DocumentDB/databaseAccounts', variables('cosmosDbAccountName')), '2019-12-12').connectionStrings[0].connectionString]" 917 | } 918 | ] 919 | } 920 | }, 921 | "resources": [ 922 | { 923 | "type": "networkConfig", 924 | "apiVersion": "2019-08-01", 925 | "name": "virtualNetwork", 926 | "dependsOn": [ 927 | "[concat('Microsoft.Web/sites/', variables('functionAppName'))]" 928 | ], 929 | "properties": { 930 | "subnetResourceId": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('vnetName'), variables('functionsSubnetName'))]", 931 | "isSwift": true 932 | } 933 | }, 934 | { 935 | "type": "config", 936 | "name": "web", 937 | "apiVersion": "2019-08-01", 938 | "dependsOn": [ 939 | "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]" 940 | ], 941 | "properties": { 942 | "functionsRuntimeScaleMonitoringEnabled": true 943 | } 944 | } 945 | ] 946 | } 947 | ], 948 | "outputs": { 949 | } 950 | } 951 | -------------------------------------------------------------------------------- /template/azuredeploy.parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "virtualMachineAdminUsername": { 6 | "value": "[YOUR-USERNAME]" 7 | }, 8 | "virtualMachineAdminPassword": { 9 | "value": "[YOUR-PASSWORD]" 10 | } 11 | } 12 | } --------------------------------------------------------------------------------