Adding an azure-nextgen example for placing app service behind vnet
ADD
azure-nextgen-ts-webapp-privateendpoint-vnet-injection/.gitignore
+/bin/
+/node_modules/

ADD
azure-nextgen-ts-webapp-privateendpoint-vnet-injection/Pulumi.yaml
+name: azure-nextgen-ts-webapp-privateendpoint-vnet-injection
+runtime: nodejs
+description: Deploy two App Services - Front web app with VNet injection and Back web app with a Private Endpoint.

ADD
azure-nextgen-ts-webapp-privateendpoint-vnet-injection/README.md
+# Deploy two App Services - Front web app with VNet injection and Back web app with a Private Endpoint
+
+**Note** This is a port of https://github.com/Azure/azure-quickstart-templates/tree/master/101-webapp-privateendpoint-vnet-injection to Pulumi's Azure-Nextgen SDK.
+
+This deploys a secure front end - back end web app. The front end web app (`site2`) is plugged in a subnet with the feature regional VNet integration enabled. Settings are set to consume a DNS private zone. The backend web app (`site1`) is only exposed through a private endpoint.
+
+It will create a VNet, two subnets, one where your Private Endpoint will exist, the second where you will inject the front web app, an App Service Plan in PremiumV2 tier (mandatory for Private Endpoint), a Private Endpoint, settings for DNS queries to the DNS Private Zone, and a private DNS zone with record for the Private Endpoint.
+
+## Required config params
+`resourceGroupNameParam` - name for the resource group.

ADD
azure-nextgen-ts-webapp-privateendpoint-vnet-injection/index.ts
+import * as azure_nextgen from "@pulumi/azure-nextgen";
+import * as pulumi from "@pulumi/pulumi";
+import * as random from "@pulumi/random";
+
+const config = new pulumi.Config();
+const resourceGroupNameParam = config.require("resourceGroupNameParam");
+
+const locationParam = config.get("locationParam") || "westus2";
+const resourceGroup = new azure_nextgen.resources.latest.ResourceGroup("resourceGroup", {
+ resourceGroupName: resourceGroupNameParam,
+ location: locationParam,
+});
+
+const serverFarmNameParam = config.get("serverFarmNameParam") || "appserverfarm";
+const skuFamilyParam = config.get("skuFamilyParam") || "P1v2";
+const skuNameParam = config.get("skuNameParam") || "P1v2";
+const skuSizeParam = config.get("skuSizeParam") || "P1v2";
+const skuTier = "PremiumV2";
+
+const serverfarm = new azure_nextgen.web.v20190801.AppServicePlan("serverfarm", {
+ kind: "app",
+ location: locationParam,
+ name: serverFarmNameParam,
+ resourceGroupName: resourceGroup.name,
+ sku: {
+ capacity: 1,
+ family: skuFamilyParam,
+ name: skuNameParam,
+ size: skuSizeParam,
+ tier: skuTier,
+ },
+});
+
+const rand = new random.RandomString("random", {
+ length: 5,
+ special: false,
+});
+const site1NameParam = config.get("site1NameParam") || pulumi.interpolate `webapp1${rand.result}`;
+const site1 = new azure_nextgen.web.v20190801.WebApp("backendApp", {
+ kind: "app",
+ location: locationParam,
+ name: site1NameParam,
+ resourceGroupName: resourceGroup.name,
+ serverFarmId: serverfarm.id,
+ siteConfig: {
+ ftpsState: azure_nextgen.web.v20190801.FtpsState.AllAllowed,
+ },
+});
+
+const webappDnsName = ".azurewebsites.net";
+new azure_nextgen.web.v20190801.WebAppHostNameBinding("hostNameBindingSite1", {
+ hostName: pulumi.interpolate `${site1.name}${webappDnsName}`,
+ hostNameType: "Verified",
+ name: pulumi.interpolate `${site1.name}${webappDnsName}`,
+ resourceGroupName: resourceGroup.name,
+ siteName: site1.name,
+});
+
+const site2NameParam = config.get("site2NameParam") || pulumi.interpolate `webapp2${rand.result}`;
+const site2 = new azure_nextgen.web.v20190801.WebApp("frontendApp", {
+ kind: "app",
+ location: locationParam,
+ name: site2NameParam,
+ resourceGroupName: resourceGroup.name,
+ serverFarmId: serverfarm.id,
+
+ siteConfig: {
+ ftpsState: azure_nextgen.web.v20190801.FtpsState.AllAllowed,
+ },
+});
+
+new azure_nextgen.web.v20190801.WebAppHostNameBinding("hostNameBindingSite2", {
+ hostName: pulumi.interpolate `${site2.name}${webappDnsName}`,
+ hostNameType: "Verified",
+ name: pulumi.interpolate `${site2.name}${webappDnsName}`,
+ resourceGroupName: resourceGroup.name,
+ siteName: site2.name,
+});
+
+const virtualNetworkNameParam = config.get("virtualNetworkNameParam") || "vnet";
+const privateDNSZoneName = "privatelink.azurewebsites.net";
+const virtualNetworkCIDRParam = config.get("virtualNetworkCIDRParam") || "10.200.0.0/16";
+const virtualNetwork = new azure_nextgen.network.v20200401.VirtualNetwork("virtualNetwork", {
+ addressSpace: {
+ addressPrefixes: [virtualNetworkCIDRParam],
+ },
+ location: locationParam,
+ resourceGroupName: resourceGroup.name,
+ virtualNetworkName: virtualNetworkNameParam,
+});
+const privateDnsZone = new azure_nextgen.network.v20180901.PrivateZone("privateDnsZone", {
+ location: "global",
+ privateZoneName: privateDNSZoneName,
+ resourceGroupName: resourceGroup.name,
+}, {
+ dependsOn: [virtualNetwork],
+});
+const privateEndpointNameParam = config.get("privateEndpointNameParam") || "PrivateEndpoint1";
+const privateLinkConnectionNameParam = config.get("privateLinkConnectionNameParam") || "PrivateEndpointLink1";
+const subnet1NameParam = config.get("subnet1NameParam") || "SubnetForSite1";
+const subnet1CIDRParam = config.get("subnet1CIDRParam") || "10.200.1.0/24";
+const subnet1 = new azure_nextgen.network.v20200401.Subnet("subnet1", {
+ addressPrefix: subnet1CIDRParam,
+ privateEndpointNetworkPolicies: "Disabled",
+ resourceGroupName: resourceGroup.name,
+ subnetName: subnet1NameParam,
+ virtualNetworkName: virtualNetwork.name,
+});
+const privateEndpoint = new azure_nextgen.network.v20200501.PrivateEndpoint("privateEndpoint", {
+ location: locationParam,
+ privateEndpointName: privateEndpointNameParam,
+ privateLinkServiceConnections: [{
+ groupIds: ["sites"],
+ name: privateLinkConnectionNameParam,
+ privateLinkServiceId: site1.id,
+ }],
+ resourceGroupName: resourceGroup.name,
+ subnet: {
+ id: subnet1.id,
+ },
+});
+new azure_nextgen.network.v20200301.PrivateDnsZoneGroup("privateDnsZoneGroup", {
+ privateDnsZoneConfigs: [{
+ name: "config1",
+ privateDnsZoneId: privateDnsZone.id,
+ }],
+ privateDnsZoneGroupName: `${privateEndpointNameParam}`,
+ privateEndpointName: privateEndpoint.name,
+ resourceGroupName: resourceGroup.name,
+});
+new azure_nextgen.network.v20180901.VirtualNetworkLink("virtualNetworkLink", {
+ location: "global",
+ privateZoneName: privateDnsZone.name,
+ registrationEnabled: false,
+ resourceGroupName: resourceGroup.name,
+ virtualNetwork: {
+ id: virtualNetwork.id,
+ },
+ virtualNetworkLinkName: pulumi.interpolate `${privateDNSZoneName}-link`,
+});
+
+const subnet2NameParam = config.get("subnet2NameParam") || "SubnetForSite2";
+const subnet2CIDRParam = config.get("subnet2CIDRParam") || "10.200.2.0/24";
+const subnet2 = new azure_nextgen.network.v20200401.Subnet("subnet2", {
+ addressPrefix: subnet2CIDRParam,
+ delegations: [{
+ name: "delegation",
+ serviceName: "Microsoft.Web/serverfarms",
+ }],
+ privateEndpointNetworkPolicies: "Enabled",
+ resourceGroupName: resourceGroup.name,
+ subnetName: subnet2NameParam,
+ virtualNetworkName: virtualNetwork.name,
+});
+
+new azure_nextgen.web.v20190801.WebAppSwiftVirtualNetworkConnection("virtualNetworkConnForSite2", {
+ name: site2.name,
+ resourceGroupName: resourceGroup.name,
+ subnetResourceId: subnet2.id,
+});
\ No newline at end of file

ADD
azure-nextgen-ts-webapp-privateendpoint-vnet-injection/package.json
+{
+ "name": "azure-nextgen-ts-webapp-privateendpoint-vnet-injection",
+ "devDependencies": {
+ "@types/node": "^10.0.0"
+ },
+ "dependencies": {
+ "@pulumi/pulumi": "^2.0.0",
+ "@pulumi/azure-nextgen": "^0.6.0",
+ "@pulumi/random": "3.0.2"
+ }
+}

ADD
azure-nextgen-ts-webapp-privateendpoint-vnet-injection/tsconfig.json
+{
+ "compilerOptions": {
+ "strict": true,
+ "outDir": "bin",
+ "target": "es2016",
+ "module": "commonjs",
+ "moduleResolution": "node",
+ "sourceMap": true,
+ "experimentalDecorators": true,
+ "pretty": true,
+ "noFallthroughCasesInSwitch": true,
+ "noImplicitReturns": true,
+ "forceConsistentCasingInFileNames": true
+ },
+ "files": [
+ "index.ts"
+ ]
+}

Adding an azure-nextgen example for placing app service behind vnet