Adds Azure deployment
This commit is contained in:
Родитель
61bad49363
Коммит
819ce5cf83
|
@ -1,7 +1,9 @@
|
||||||
.env
|
.env
|
||||||
.git
|
.git
|
||||||
|
.github
|
||||||
.vscode
|
.vscode
|
||||||
build
|
build
|
||||||
|
dist
|
||||||
docs
|
docs
|
||||||
*Dockerfile*
|
*Dockerfile*
|
||||||
node_modules
|
node_modules
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
tunnels:
|
||||||
|
deploy:
|
||||||
|
addr: 8080
|
||||||
|
proto: http
|
||||||
|
bind_tls: true
|
|
@ -2,6 +2,8 @@
|
||||||
"recommendations": [
|
"recommendations": [
|
||||||
"hbenl.vscode-mocha-test-adapter",
|
"hbenl.vscode-mocha-test-adapter",
|
||||||
"humao.rest-client",
|
"humao.rest-client",
|
||||||
|
"ms-azuretools.vscode-azureappservice",
|
||||||
|
"msazurermtools.azurerm-vscode-tools",
|
||||||
"visualstudioexptteam.vscodeintellicode"
|
"visualstudioexptteam.vscodeintellicode"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ RUN chown node:node .
|
||||||
USER node
|
USER node
|
||||||
|
|
||||||
COPY --from=build /app/package*.json ./
|
COPY --from=build /app/package*.json ./
|
||||||
RUN npm install --ignore-scripts
|
RUN npm install
|
||||||
|
|
||||||
COPY --from=build /app/build/src /app/build/src
|
COPY --from=build /app/build/src /app/build/src
|
||||||
|
|
||||||
|
|
15
README.md
15
README.md
|
@ -217,9 +217,22 @@ f4156ae0-6bad-11ea-bd94-8fa64eaf2878 unknown 2020-03-21 12:55:45 PDT
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
## Deploying SDS to the cloud
|
## Deploying SDS to the cloud
|
||||||
TODO: instructions for Azure deployment and client configuration.
|
|
||||||
|
|
||||||
|
Requirements
|
||||||
|
|
||||||
|
* [azure-cli](https://aka.ms/azure-cli)
|
||||||
|
* [jq](https://stedolan.github.io/jq/)
|
||||||
|
* [Packer](https://www.packer.io/)
|
||||||
|
|
||||||
|
Run the following commands in a bash terminal
|
||||||
|
|
||||||
|
~~~
|
||||||
|
# Create a resource group to hold all the sandbox resources
|
||||||
|
az group create -n sandbox -l southcentralus
|
||||||
|
|
||||||
|
# Deploy an instance of the sandbox
|
||||||
|
./deploy/deploy.sh -g sandbox
|
||||||
|
~~~
|
||||||
|
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
|
||||||
|
"contentVersion": "1.0.0.0",
|
||||||
|
"parameters": {
|
||||||
|
"assetsBaseUrl": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": ""
|
||||||
|
},
|
||||||
|
"baseName": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "dct"
|
||||||
|
},
|
||||||
|
"sshPublicKey": {
|
||||||
|
"type": "securestring",
|
||||||
|
"defaultValue": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": {
|
||||||
|
"assetsBaseUrl": "[if(empty(parameters('assetsBaseUrl')), if(contains(deployment().properties, 'templateLink'), uri(deployment().properties.templateLink.uri, '../'), 'https://raw.githubusercontent.com/microsoft/data-contest-toolkit/master/deploy/'), parameters('assetsBaseUrl'))]",
|
||||||
|
"environmentDeployment": "azuredeploy"
|
||||||
|
},
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"type": "Microsoft.Resources/deployments",
|
||||||
|
"apiVersion": "2017-05-10",
|
||||||
|
"name": "[variables('environmentDeployment')]",
|
||||||
|
"resourceGroup": "[resourceGroup().name]",
|
||||||
|
"properties": {
|
||||||
|
"mode": "Incremental",
|
||||||
|
"parameters": {
|
||||||
|
"assetsBaseUrl": {
|
||||||
|
"value": "[parameters('assetsBaseUrl')]"
|
||||||
|
},
|
||||||
|
"baseName": {
|
||||||
|
"value": "[parameters('baseName')]"
|
||||||
|
},
|
||||||
|
"workerVmSize": {
|
||||||
|
"value": "Standard_B2s"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"templateLink": {
|
||||||
|
"uri": "[uri(variables('assetsBaseUrl'), './azure/azuredeploy.json')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.Resources/deployments', variables('environmentDeployment'))]"
|
||||||
|
],
|
||||||
|
"type": "Microsoft.Resources/deployments",
|
||||||
|
"apiVersion": "2017-05-10",
|
||||||
|
"name": "dev",
|
||||||
|
"resourceGroup": "[resourceGroup().name]",
|
||||||
|
"properties": {
|
||||||
|
"mode": "Incremental",
|
||||||
|
"parameters": {
|
||||||
|
"sshPublicKey": {
|
||||||
|
"value": "[parameters('sshPublicKey')]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"templateLink": {
|
||||||
|
"uri": "[uri(variables('assetsBaseUrl'), './azure/dev.json')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outputs": {
|
||||||
|
"laboratorySiteId": {
|
||||||
|
"type": "string",
|
||||||
|
"value": "[reference(variables('environmentDeployment')).outputs.laboratorySiteId.value]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,217 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
|
||||||
|
"contentVersion": "1.0.0.0",
|
||||||
|
"parameters": {
|
||||||
|
"assetsBaseUrl": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": ""
|
||||||
|
},
|
||||||
|
"baseName": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "dct"
|
||||||
|
},
|
||||||
|
"workerVmSize": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "Standard_DS2_v2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": {
|
||||||
|
"assetsBaseUrl": "[if(empty(parameters('assetsBaseUrl')), if(contains(deployment().properties, 'templateLink'), uri(deployment().properties.templateLink.uri, '../'), 'https://raw.githubusercontent.com/microsoft/data-contest-toolkit/master/deploy/'), parameters('assetsBaseUrl'))]",
|
||||||
|
"bootstrapIdentity": "bootstrap",
|
||||||
|
"bootstrapDeployment": "bootstrap",
|
||||||
|
"laboratoryDeployment": "laboratory",
|
||||||
|
"monitoringDeployment": "monitoring",
|
||||||
|
"networkDeployment": "network",
|
||||||
|
"privatelinkDeployment": "privatelink",
|
||||||
|
"workerDeployment": "worker",
|
||||||
|
"workerIdentity": "worker"
|
||||||
|
},
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"type": "Microsoft.ManagedIdentity/userAssignedIdentities",
|
||||||
|
"apiVersion": "2018-11-30",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"name": "[variables('bootstrapIdentity')]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Microsoft.ManagedIdentity/userAssignedIdentities",
|
||||||
|
"apiVersion": "2018-11-30",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"name": "[variables('workerIdentity')]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Microsoft.Resources/deployments",
|
||||||
|
"apiVersion": "2017-05-10",
|
||||||
|
"name": "[variables('networkDeployment')]",
|
||||||
|
"resourceGroup": "[resourceGroup().name]",
|
||||||
|
"properties": {
|
||||||
|
"mode": "Incremental",
|
||||||
|
"templateLink": {
|
||||||
|
"uri": "[uri(variables('assetsBaseUrl'), './azure/network.json')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('bootstrapIdentity'))]",
|
||||||
|
"[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('workerIdentity'))]",
|
||||||
|
"[resourceId('Microsoft.Resources/deployments', variables('networkDeployment'))]"
|
||||||
|
],
|
||||||
|
"type": "Microsoft.Resources/deployments",
|
||||||
|
"apiVersion": "2017-05-10",
|
||||||
|
"name": "[variables('laboratoryDeployment')]",
|
||||||
|
"resourceGroup": "[resourceGroup().name]",
|
||||||
|
"properties": {
|
||||||
|
"mode": "Incremental",
|
||||||
|
"parameters": {
|
||||||
|
"baseName": {
|
||||||
|
"value": "[parameters('baseName')]"
|
||||||
|
},
|
||||||
|
"bootstrapIdentityId": {
|
||||||
|
"value": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('bootstrapIdentity'))]"
|
||||||
|
},
|
||||||
|
"privateDnsId": {
|
||||||
|
"value": "[reference(variables('networkDeployment')).outputs.privateDnsId.value]"
|
||||||
|
},
|
||||||
|
"subnetId": {
|
||||||
|
"value": "[reference(variables('networkDeployment')).outputs.laboratorySubnetId.value]"
|
||||||
|
},
|
||||||
|
"workerIdentityId": {
|
||||||
|
"value": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('workerIdentity'))]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"templateLink": {
|
||||||
|
"uri": "[uri(variables('assetsBaseUrl'), './azure/laboratory.json')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.Resources/deployments', variables('laboratoryDeployment'))]",
|
||||||
|
"[resourceId('Microsoft.Resources/deployments', variables('networkDeployment'))]"
|
||||||
|
],
|
||||||
|
"type": "Microsoft.Resources/deployments",
|
||||||
|
"apiVersion": "2017-05-10",
|
||||||
|
"name": "[variables('privatelinkDeployment')]",
|
||||||
|
"resourceGroup": "[resourceGroup().name]",
|
||||||
|
"properties": {
|
||||||
|
"mode": "Incremental",
|
||||||
|
"parameters": {
|
||||||
|
"laboratoryRegistryId": {
|
||||||
|
"value": "[reference(variables('laboratoryDeployment')).outputs.registryId.value]"
|
||||||
|
},
|
||||||
|
"laboratorySqlServerId": {
|
||||||
|
"value": "[reference(variables('laboratoryDeployment')).outputs.sqlServerId.value]"
|
||||||
|
},
|
||||||
|
"laboratoryStorageAccountId": {
|
||||||
|
"value": "[reference(variables('laboratoryDeployment')).outputs.storageAccountId.value]"
|
||||||
|
},
|
||||||
|
"subnetId": {
|
||||||
|
"value": "[reference(variables('networkDeployment')).outputs.paasSubnetId.value]"
|
||||||
|
},
|
||||||
|
"vnetId": {
|
||||||
|
"value": "[reference(variables('networkDeployment')).outputs.vnetId.value]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"templateLink": {
|
||||||
|
"uri": "[uri(variables('assetsBaseUrl'), './azure/privatelink.json')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('workerIdentity'))]",
|
||||||
|
"[resourceId('Microsoft.Resources/deployments', variables('bootstrapDeployment'))]",
|
||||||
|
"[resourceId('Microsoft.Resources/deployments', variables('laboratoryDeployment'))]",
|
||||||
|
"[resourceId('Microsoft.Resources/deployments', variables('networkDeployment'))]"
|
||||||
|
],
|
||||||
|
"type": "Microsoft.Resources/deployments",
|
||||||
|
"apiVersion": "2017-05-10",
|
||||||
|
"name": "[variables('workerDeployment')]",
|
||||||
|
"resourceGroup": "[resourceGroup().name]",
|
||||||
|
"properties": {
|
||||||
|
"mode": "Incremental",
|
||||||
|
"parameters": {
|
||||||
|
"asgId": {
|
||||||
|
"value": "[reference(variables('networkDeployment')).outputs.workerAsgId.value]"
|
||||||
|
},
|
||||||
|
"identityId": {
|
||||||
|
"value": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('workerIdentity'))]"
|
||||||
|
},
|
||||||
|
"subnetId": {
|
||||||
|
"value": "[reference(variables('networkDeployment')).outputs.lockdownSubnetId.value]"
|
||||||
|
},
|
||||||
|
"vmSize": {
|
||||||
|
"value": "[parameters('workerVmSize')]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"templateLink": {
|
||||||
|
"uri": "[uri(variables('assetsBaseUrl'), './azure/worker.vm.json')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.Resources/deployments', variables('laboratoryDeployment'))]"
|
||||||
|
],
|
||||||
|
"type": "Microsoft.Resources/deployments",
|
||||||
|
"apiVersion": "2017-05-10",
|
||||||
|
"name": "[variables('monitoringDeployment')]",
|
||||||
|
"resourceGroup": "[resourceGroup().name]",
|
||||||
|
"properties": {
|
||||||
|
"mode": "Incremental",
|
||||||
|
"parameters": {
|
||||||
|
"baseName": {
|
||||||
|
"value": "[parameters('baseName')]"
|
||||||
|
},
|
||||||
|
"laboratorySiteId": {
|
||||||
|
"value": "[reference(variables('laboratoryDeployment')).outputs.siteId.value]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"templateLink": {
|
||||||
|
"uri": "[uri(variables('assetsBaseUrl'), './azure/monitoring.json')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('bootstrapIdentity'))]",
|
||||||
|
"[resourceId('Microsoft.Resources/deployments', variables('laboratoryDeployment'))]",
|
||||||
|
"[resourceId('Microsoft.Resources/deployments', variables('monitoringDeployment'))]",
|
||||||
|
"[resourceId('Microsoft.Resources/deployments', variables('networkDeployment'))]",
|
||||||
|
"[resourceId('Microsoft.Resources/deployments', variables('privatelinkDeployment'))]"
|
||||||
|
],
|
||||||
|
"type": "Microsoft.Resources/deployments",
|
||||||
|
"apiVersion": "2017-05-10",
|
||||||
|
"name": "[variables('bootstrapDeployment')]",
|
||||||
|
"resourceGroup": "[resourceGroup().name]",
|
||||||
|
"properties": {
|
||||||
|
"mode": "Incremental",
|
||||||
|
"parameters": {
|
||||||
|
"asgId": {
|
||||||
|
"value": "[reference(variables('networkDeployment')).outputs.bootstrapAsgId.value]"
|
||||||
|
},
|
||||||
|
"identityId": {
|
||||||
|
"value": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('bootstrapIdentity'))]"
|
||||||
|
},
|
||||||
|
"subnetId": {
|
||||||
|
"value": "[reference(variables('networkDeployment')).outputs.bootstrapSubnetId.value]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"templateLink": {
|
||||||
|
"uri": "[uri(variables('assetsBaseUrl'), './azure/bootstrap.json')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outputs": {
|
||||||
|
"laboratoryRegistryName": {
|
||||||
|
"type": "string",
|
||||||
|
"value": "[last(split(reference(variables('laboratoryDeployment')).outputs.registryId.value, '/'))]"
|
||||||
|
},
|
||||||
|
"laboratorySiteId": {
|
||||||
|
"type": "string",
|
||||||
|
"value": "[reference(variables('laboratoryDeployment')).outputs.siteId.value]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,149 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
|
||||||
|
"contentVersion": "1.0.0.0",
|
||||||
|
"parameters": {
|
||||||
|
"assetsBaseUrl": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": ""
|
||||||
|
},
|
||||||
|
"asgId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"identityId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"subnetId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"vmPassword": {
|
||||||
|
"type": "securestring",
|
||||||
|
"defaultValue": "[newGuid()]"
|
||||||
|
},
|
||||||
|
"vmSize": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "Standard_B1s"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": {
|
||||||
|
"assetsBaseUrl": "[if(empty(parameters('assetsBaseUrl')), if(contains(deployment().properties, 'templateLink'), uri(deployment().properties.templateLink.uri, '../'), 'https://raw.githubusercontent.com/microsoft/data-contest-toolkit/master/deploy/'), parameters('assetsBaseUrl'))]",
|
||||||
|
"cloudInit": [
|
||||||
|
"[uri(variables('assetsBaseUrl'), './bootstrap/setup.sh')]",
|
||||||
|
"[uri(variables('assetsBaseUrl'), './bootstrap/bootstrap.ps1')]"
|
||||||
|
],
|
||||||
|
"customData": "[base64(format('#include\n{0}', util.join(variables('cloudInit'), '\n')))]",
|
||||||
|
"name": "bootstrap",
|
||||||
|
"virtualMachineContributorRoleId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]"
|
||||||
|
},
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"type": "Microsoft.Network/networkInterfaces",
|
||||||
|
"apiVersion": "2019-11-01",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"name": "[variables('name')]",
|
||||||
|
"properties": {
|
||||||
|
"ipConfigurations": [
|
||||||
|
{
|
||||||
|
"name": "default",
|
||||||
|
"properties": {
|
||||||
|
"applicationSecurityGroups": [
|
||||||
|
{
|
||||||
|
"id": "[parameters('asgId')]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"privateIPAllocationMethod": "Dynamic",
|
||||||
|
"subnet": {
|
||||||
|
"id": "[parameters('subnetId')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.Network/networkInterfaces', variables('name'))]"
|
||||||
|
],
|
||||||
|
"type": "Microsoft.Compute/virtualMachines",
|
||||||
|
"apiVersion": "2019-07-01",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"name": "[variables('name')]",
|
||||||
|
"identity": {
|
||||||
|
"type": "UserAssigned",
|
||||||
|
"userAssignedIdentities": {
|
||||||
|
"[parameters('identityId')]": {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"hardwareProfile": {
|
||||||
|
"vmSize": "[parameters('vmSize')]"
|
||||||
|
},
|
||||||
|
"networkProfile": {
|
||||||
|
"networkInterfaces": [
|
||||||
|
{
|
||||||
|
"id": "[resourceId('Microsoft.Network/networkInterfaces', variables('name'))]"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"osProfile": {
|
||||||
|
"adminUsername": "azureuser",
|
||||||
|
"adminPassword": "[parameters('vmPassword')]",
|
||||||
|
"computerName": "[variables('name')]",
|
||||||
|
"customData": "[variables('customData')]"
|
||||||
|
},
|
||||||
|
"storageProfile": {
|
||||||
|
"imageReference": {
|
||||||
|
"publisher": "Canonical",
|
||||||
|
"offer": "UbuntuServer",
|
||||||
|
"sku": "18.04-LTS",
|
||||||
|
"version": "latest"
|
||||||
|
},
|
||||||
|
"osDisk": {
|
||||||
|
"createOption": "FromImage",
|
||||||
|
"managedDisk": {
|
||||||
|
"storageAccountType": "Standard_LRS"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.Compute/virtualMachines', variables('name'))]"
|
||||||
|
],
|
||||||
|
"type": "providers/roleAssignments",
|
||||||
|
"apiVersion": "2018-09-01-preview",
|
||||||
|
"name": "[concat('Microsoft.Authorization/', guid(concat(variables('name'), parameters('identityId'), 'VirtualMachineContributor')))]",
|
||||||
|
"properties": {
|
||||||
|
"roleDefinitionId": "[variables('virtualMachineContributorRoleId')]",
|
||||||
|
"principalId": "[reference(parameters('identityId'), '2018-11-30').principalId]",
|
||||||
|
"principalType": "ServicePrincipal"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"functions": [
|
||||||
|
{
|
||||||
|
"namespace": "util",
|
||||||
|
"members": {
|
||||||
|
"join": {
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "values",
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "separator",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"output": {
|
||||||
|
"type": "string",
|
||||||
|
"value": "[replace(replace(substring(string(parameters('values')), 1, sub(length(string(parameters('values'))), 2)), '\"', ''), ',', parameters('separator'))]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,219 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
|
||||||
|
"contentVersion": "1.0.0.0",
|
||||||
|
"parameters": {
|
||||||
|
"sshPublicKey": {
|
||||||
|
"type": "securestring",
|
||||||
|
"defaultValue": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": {
|
||||||
|
"autoShutdownTime": "0200",
|
||||||
|
"autoShutdownTimeZone": "UTC",
|
||||||
|
"bootstrapIp": "bootstrap-dev",
|
||||||
|
"tags": {
|
||||||
|
"dct-mode": "development"
|
||||||
|
},
|
||||||
|
"workerIp": "worker-dev"
|
||||||
|
},
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"name": "default",
|
||||||
|
"type": "Microsoft.Resources/tags",
|
||||||
|
"apiVersion": "2019-10-01",
|
||||||
|
"properties": {
|
||||||
|
"tags": "[union(resourceGroup().tags, variables('tags'))]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "shutdown-computevm-bootstrap",
|
||||||
|
"type": "Microsoft.DevTestLab/schedules",
|
||||||
|
"apiVersion": "2018-09-15",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"properties": {
|
||||||
|
"status": "Enabled",
|
||||||
|
"dailyRecurrence": {
|
||||||
|
"time": "[variables('autoShutdownTime')]"
|
||||||
|
},
|
||||||
|
"targetResourceId": "[resourceId('Microsoft.Compute/virtualMachines', 'bootstrap')]",
|
||||||
|
"taskType": "ComputeVmShutdownTask",
|
||||||
|
"timeZoneId": "[variables('autoShutdownTimeZone')]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "shutdown-computevm-worker",
|
||||||
|
"type": "Microsoft.DevTestLab/schedules",
|
||||||
|
"apiVersion": "2018-09-15",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"properties": {
|
||||||
|
"status": "Enabled",
|
||||||
|
"dailyRecurrence": {
|
||||||
|
"time": "[variables('autoShutdownTime')]"
|
||||||
|
},
|
||||||
|
"targetResourceId": "[resourceId('Microsoft.Compute/virtualMachines', 'worker')]",
|
||||||
|
"taskType": "ComputeVmShutdownTask",
|
||||||
|
"timeZoneId": "[variables('autoShutdownTimeZone')]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "bootstrap/dev-ssh",
|
||||||
|
"type": "Microsoft.Network/networkSecurityGroups/securityRules",
|
||||||
|
"apiVersion": "2019-11-01",
|
||||||
|
"properties": {
|
||||||
|
"description": "Allow SSH for development",
|
||||||
|
"priority": 2000,
|
||||||
|
"direction": "Inbound",
|
||||||
|
"access": "Allow",
|
||||||
|
"protocol": "TCP",
|
||||||
|
"sourceAddressPrefix": "*",
|
||||||
|
"sourcePortRange": "*",
|
||||||
|
"destinationApplicationSecurityGroups": [
|
||||||
|
{
|
||||||
|
"id": "[resourceId('Microsoft.Network/applicationSecurityGroups', 'bootstrap')]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"destinationPortRange": "22"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "lockdown/dev-ssh",
|
||||||
|
"type": "Microsoft.Network/networkSecurityGroups/securityRules",
|
||||||
|
"apiVersion": "2019-11-01",
|
||||||
|
"properties": {
|
||||||
|
"description": "Allow SSH for development",
|
||||||
|
"priority": 2000,
|
||||||
|
"direction": "Inbound",
|
||||||
|
"access": "Allow",
|
||||||
|
"protocol": "TCP",
|
||||||
|
"sourceAddressPrefix": "*",
|
||||||
|
"sourcePortRange": "*",
|
||||||
|
"destinationApplicationSecurityGroups": [
|
||||||
|
{
|
||||||
|
"id": "[resourceId('Microsoft.Network/applicationSecurityGroups', 'worker')]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"destinationPortRange": "22"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "[variables('bootstrapIp')]",
|
||||||
|
"type": "Microsoft.Network/publicIPAddresses",
|
||||||
|
"apiVersion": "2019-11-01",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"properties": {
|
||||||
|
"publicIPAllocationMethod": "Static"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.Network/publicIPAddresses', variables('bootstrapIp'))]"
|
||||||
|
],
|
||||||
|
"type": "Microsoft.Network/networkInterfaces",
|
||||||
|
"apiVersion": "2019-11-01",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"name": "bootstrap",
|
||||||
|
"properties": {
|
||||||
|
"ipConfigurations": [
|
||||||
|
{
|
||||||
|
"name": "default",
|
||||||
|
"properties": {
|
||||||
|
"applicationSecurityGroups": [
|
||||||
|
{
|
||||||
|
"id": "[resourceId('Microsoft.Network/applicationSecurityGroups', 'bootstrap')]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"privateIPAllocationMethod": "Dynamic",
|
||||||
|
"publicIPAddress": {
|
||||||
|
"id": "[resourceId('Microsoft.Network/publicIPAddresses', variables('bootstrapIp'))]"
|
||||||
|
},
|
||||||
|
"subnet": {
|
||||||
|
"id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', 'environment', 'bootstrap')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "[variables('workerIp')]",
|
||||||
|
"type": "Microsoft.Network/publicIPAddresses",
|
||||||
|
"apiVersion": "2019-11-01",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"properties": {
|
||||||
|
"publicIPAllocationMethod": "Static"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.Network/publicIPAddresses', variables('workerIp'))]"
|
||||||
|
],
|
||||||
|
"type": "Microsoft.Network/networkInterfaces",
|
||||||
|
"apiVersion": "2019-11-01",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"name": "worker",
|
||||||
|
"properties": {
|
||||||
|
"ipConfigurations": [
|
||||||
|
{
|
||||||
|
"name": "default",
|
||||||
|
"properties": {
|
||||||
|
"applicationSecurityGroups": [
|
||||||
|
{
|
||||||
|
"id": "[resourceId('Microsoft.Network/applicationSecurityGroups', 'worker')]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"privateIPAllocationMethod": "Dynamic",
|
||||||
|
"publicIPAddress": {
|
||||||
|
"id": "[resourceId('Microsoft.Network/publicIPAddresses', variables('workerIp'))]"
|
||||||
|
},
|
||||||
|
"subnet": {
|
||||||
|
"id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', 'environment', 'lockdown')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.Network/networkInterfaces', 'bootstrap')]"
|
||||||
|
],
|
||||||
|
"condition": "[not(empty(parameters('sshPublicKey')))]",
|
||||||
|
"type": "Microsoft.Compute/virtualMachines/extensions",
|
||||||
|
"apiVersion": "2019-07-01",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"name": "bootstrap/vmAccess",
|
||||||
|
"properties": {
|
||||||
|
"publisher": "Microsoft.OSTCExtensions",
|
||||||
|
"type": "VMAccessForLinux",
|
||||||
|
"typeHandlerVersion": "1.5",
|
||||||
|
"autoUpgradeMinorVersion": true,
|
||||||
|
"settings": {},
|
||||||
|
"protectedSettings": {
|
||||||
|
"username": "azureuser",
|
||||||
|
"ssh_key": "[parameters('sshPublicKey')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.Network/networkInterfaces', 'worker')]"
|
||||||
|
],
|
||||||
|
"condition": "[not(empty(parameters('sshPublicKey')))]",
|
||||||
|
"type": "Microsoft.Compute/virtualMachines/extensions",
|
||||||
|
"apiVersion": "2019-07-01",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"name": "worker/vmAccess",
|
||||||
|
"properties": {
|
||||||
|
"publisher": "Microsoft.OSTCExtensions",
|
||||||
|
"type": "VMAccessForLinux",
|
||||||
|
"typeHandlerVersion": "1.5",
|
||||||
|
"autoUpgradeMinorVersion": true,
|
||||||
|
"settings": {},
|
||||||
|
"protectedSettings": {
|
||||||
|
"username": "azureuser",
|
||||||
|
"ssh_key": "[parameters('sshPublicKey')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,412 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
|
||||||
|
"contentVersion": "1.0.0.0",
|
||||||
|
"parameters": {
|
||||||
|
"bootstrapIdentityId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"privateDnsId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"subnetId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"workerIdentityId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"baseName": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "dct"
|
||||||
|
},
|
||||||
|
"sqlAdminUsername": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "[parameters('baseName')]"
|
||||||
|
},
|
||||||
|
"sqlAdminPassword": {
|
||||||
|
"type": "securestring",
|
||||||
|
"defaultValue": "[newGuid()]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": {
|
||||||
|
"acrPullRoleId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')]",
|
||||||
|
"appSvcPlan": "laboratory",
|
||||||
|
"identity": "laboratory",
|
||||||
|
"metadataStorage": "[concat(variables('prefix'), 'laboratory')]",
|
||||||
|
"privateDns": "[last(split(parameters('privateDnsId'), '/'))]",
|
||||||
|
"registry": "[concat(variables('prefix'), 'laboratory')]",
|
||||||
|
"runsContainer": "runs",
|
||||||
|
"runsQueue": "runs",
|
||||||
|
"site": "[concat(variables('prefix'), '-laboratory')]",
|
||||||
|
"sqlDatabase": "laboratory",
|
||||||
|
"sqlServer": "[concat(variables('prefix'), '-laboratory')]",
|
||||||
|
"prefix": "[toLower(concat(parameters('baseName'), take(uniqueString(resourceGroup().id), 6)))]",
|
||||||
|
"storageBlobDataContributorRoleId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')]",
|
||||||
|
"storageQueueDataContributorRoleId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88')]",
|
||||||
|
"storageQueueDataMessageProcessorRoleId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed')]",
|
||||||
|
"storageQueueDataMessageSenderRoleId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a')]"
|
||||||
|
},
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"type": "Microsoft.ManagedIdentity/userAssignedIdentities",
|
||||||
|
"apiVersion": "2018-11-30",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"name": "[variables('identity')]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Microsoft.Storage/storageAccounts",
|
||||||
|
"apiVersion": "2019-06-01",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"name": "[variables('metadataStorage')]",
|
||||||
|
"kind": "StorageV2",
|
||||||
|
"sku": {
|
||||||
|
"name": "Standard_LRS"
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"accessTier": "Hot",
|
||||||
|
"encryption": {
|
||||||
|
"keySource": "Microsoft.Storage",
|
||||||
|
"services": {
|
||||||
|
"blob": {
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"queue": {
|
||||||
|
"enabled": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"isHnsEnabled": false,
|
||||||
|
"networkAcls": {
|
||||||
|
"bypass": "None",
|
||||||
|
"defaultAction": "Deny",
|
||||||
|
"virtualNetworkRules": [
|
||||||
|
{
|
||||||
|
"id": "[parameters('subnetId')]",
|
||||||
|
"action": "Allow"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"supportsHttpsTrafficOnly": true
|
||||||
|
},
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('identity'))]",
|
||||||
|
"[resourceId('Microsoft.Storage/storageAccounts', variables('metadataStorage'))]"
|
||||||
|
],
|
||||||
|
"type": "providers/roleAssignments",
|
||||||
|
"apiVersion": "2018-09-01-preview",
|
||||||
|
"name": "[concat('Microsoft.Authorization/', guid(concat(variables('metadataStorage'), variables('identity'), 'StorageQueueDataMessageSender')))]",
|
||||||
|
"properties": {
|
||||||
|
"roleDefinitionId": "[variables('storageQueueDataMessageSenderRoleId')]",
|
||||||
|
"principalId": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('identity'))).principalId]",
|
||||||
|
"principalType": "ServicePrincipal"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.Storage/storageAccounts', variables('metadataStorage'))]"
|
||||||
|
],
|
||||||
|
"type": "providers/roleAssignments",
|
||||||
|
"apiVersion": "2018-09-01-preview",
|
||||||
|
"name": "[concat('Microsoft.Authorization/', guid(concat(variables('metadataStorage'), parameters('bootstrapIdentityId'), 'StorageQueueDataContributor')))]",
|
||||||
|
"properties": {
|
||||||
|
"roleDefinitionId": "[variables('storageQueueDataContributorRoleId')]",
|
||||||
|
"principalId": "[reference(parameters('bootstrapIdentityId'), '2018-11-30').principalId]",
|
||||||
|
"principalType": "ServicePrincipal"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.Storage/storageAccounts', variables('metadataStorage'))]"
|
||||||
|
],
|
||||||
|
"type": "providers/roleAssignments",
|
||||||
|
"apiVersion": "2018-09-01-preview",
|
||||||
|
"name": "[concat('Microsoft.Authorization/', guid(concat(variables('metadataStorage'), parameters('workerIdentityId'), 'StorageQueueDataMessageProcessor')))]",
|
||||||
|
"properties": {
|
||||||
|
"roleDefinitionId": "[variables('storageQueueDataMessageProcessorRoleId')]",
|
||||||
|
"principalId": "[reference(parameters('workerIdentityId'), '2018-11-30').principalId]",
|
||||||
|
"principalType": "ServicePrincipal"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.Storage/storageAccounts', variables('metadataStorage'))]"
|
||||||
|
],
|
||||||
|
"type": "blobServices/containers",
|
||||||
|
"apiVersion": "2019-06-01",
|
||||||
|
"name": "[concat('default/', variables('runsContainer'))]",
|
||||||
|
"properties": {
|
||||||
|
"publicAccess": "None"
|
||||||
|
},
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.Storage/storageAccounts/blobServices/containers', variables('metadataStorage'), 'default', variables('runsContainer'))]"
|
||||||
|
],
|
||||||
|
"type": "providers/roleAssignments",
|
||||||
|
"apiVersion": "2018-09-01-preview",
|
||||||
|
"name": "[concat('/Microsoft.Authorization/', guid(variables('metadataStorage'), variables('runsContainer'), parameters('workerIdentityId'), 'StorageBlobDataContributor'))]",
|
||||||
|
"properties": {
|
||||||
|
"roleDefinitionId": "[variables('storageBlobDataContributorRoleId')]",
|
||||||
|
"principalId": "[reference(parameters('workerIdentityId'), '2018-11-30').principalId]",
|
||||||
|
"principalType": "ServicePrincipal"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Microsoft.Sql/servers",
|
||||||
|
"apiVersion": "2019-06-01-preview",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"name": "[variables('sqlServer')]",
|
||||||
|
"properties": {
|
||||||
|
"administratorLogin": "[parameters('sqlAdminUsername')]",
|
||||||
|
"administratorLoginPassword": "[parameters('sqlAdminPassword')]",
|
||||||
|
"minimalTlsVersion": "1.2",
|
||||||
|
"version": "12.0"
|
||||||
|
},
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.Sql/servers', variables('sqlServer'))]"
|
||||||
|
],
|
||||||
|
"type": "administrators",
|
||||||
|
"apiVersion": "2019-06-01-preview",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"name": "ActiveDirectory",
|
||||||
|
"properties": {
|
||||||
|
"administratorType": "ActiveDirectory",
|
||||||
|
"login": "[last(split(parameters('bootstrapIdentityId'), '/'))]",
|
||||||
|
"sid": "[reference(parameters('bootstrapIdentityId'), '2018-11-30').principalId]",
|
||||||
|
"tenantId": "[subscription().tenantId]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.Sql/servers', variables('sqlServer'))]"
|
||||||
|
],
|
||||||
|
"type": "databases",
|
||||||
|
"apiVersion": "2019-06-01-preview",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"name": "[variables('sqlDatabase')]",
|
||||||
|
"sku": {
|
||||||
|
"name": "GP_S_Gen5",
|
||||||
|
"capacity": 1
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"autoPauseDelay": 60,
|
||||||
|
"minCapacity": 0.5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.Sql/servers', variables('sqlServer'))]"
|
||||||
|
],
|
||||||
|
"type": "virtualNetworkRules",
|
||||||
|
"apiVersion": "2015-05-01-preview",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"name": "laboratory",
|
||||||
|
"properties": {
|
||||||
|
"virtualNetworkSubnetId": "[parameters('subnetId')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Microsoft.ContainerRegistry/registries",
|
||||||
|
"apiVersion": "2019-12-01-preview",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"name": "[variables('registry')]",
|
||||||
|
"sku": {
|
||||||
|
"name": "Premium"
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"adminUserEnabled": false,
|
||||||
|
"networkRuleSet": {
|
||||||
|
"defaultAction": "Deny"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.ContainerRegistry/registries', variables('registry'))]"
|
||||||
|
],
|
||||||
|
"type": "providers/roleAssignments",
|
||||||
|
"apiVersion": "2018-09-01-preview",
|
||||||
|
"name": "[concat('Microsoft.Authorization/', guid(concat(variables('registry'), parameters('workerIdentityId'), 'AcrPull')))]",
|
||||||
|
"properties": {
|
||||||
|
"roleDefinitionId": "[variables('acrPullRoleId')]",
|
||||||
|
"principalId": "[reference(parameters('workerIdentityId'), '2018-11-30').principalId]",
|
||||||
|
"principalType": "ServicePrincipal"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Microsoft.Web/serverFarms",
|
||||||
|
"apiVersion": "2019-08-01",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"name": "[variables('appSvcPlan')]",
|
||||||
|
"kind": "linux",
|
||||||
|
"sku": {
|
||||||
|
"name": "S1"
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"reserved": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('identity'))]",
|
||||||
|
"[resourceId('Microsoft.Sql/servers', variables('sqlServer'))]",
|
||||||
|
"[resourceId('Microsoft.Storage/storageAccounts', variables('metadataStorage'))]",
|
||||||
|
"[resourceId('Microsoft.Web/serverFarms', variables('appSvcPlan'))]"
|
||||||
|
],
|
||||||
|
"type": "Microsoft.Web/sites",
|
||||||
|
"apiVersion": "2019-08-01",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"name": "[variables('site')]",
|
||||||
|
"identity": {
|
||||||
|
"type": "UserAssigned",
|
||||||
|
"userAssignedIdentities": {
|
||||||
|
"[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('identity'))]": {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"httpsOnly": true,
|
||||||
|
"serverFarmId": "[resourceId('Microsoft.Web/serverFarms', variables('appSvcPlan'))]",
|
||||||
|
"siteConfig": {
|
||||||
|
"alwaysOn": true,
|
||||||
|
"appCommandLine": "npm run laboratory",
|
||||||
|
"appSettings": [
|
||||||
|
{
|
||||||
|
"name": "AZURE_CLIENT_ID",
|
||||||
|
"value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('identity'))).clientId]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "BLOB_CONTAINER",
|
||||||
|
"value": "[concat(reference(resourceId('Microsoft.Storage/storageAccounts', variables('metadataStorage'))).primaryEndpoints.blob, variables('runsContainer'))]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "QUEUE_MODE",
|
||||||
|
"value": "azure"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "QUEUE_ENDPOINT",
|
||||||
|
"value": "[concat(reference(resourceId('Microsoft.Storage/storageAccounts', variables('metadataStorage'))).primaryEndpoints.queue, variables('runsQueue'))]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "SQL_MODE",
|
||||||
|
"value": "azuresql"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "SQL_HOST",
|
||||||
|
"value": "[reference(resourceId('Microsoft.Sql/servers', variables('sqlServer'))).fullyQualifiedDomainName]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "SQL_DB",
|
||||||
|
"value": "[variables('sqlDatabase')]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "WEBSITE_RUN_FROM_PACKAGE",
|
||||||
|
"value": "1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"linuxFxVersion": "NODE|12-lts",
|
||||||
|
"minTlsVersion": "1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.Web/sites', variables('site'))]"
|
||||||
|
],
|
||||||
|
"type": "networkConfig",
|
||||||
|
"apiVersion": "2019-08-01",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"name": "virtualNetwork",
|
||||||
|
"properties": {
|
||||||
|
"swiftSupported": true,
|
||||||
|
"subnetResourceId": "[parameters('subnetId')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.ContainerRegistry/registries', variables('registry'))]",
|
||||||
|
"[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('identity'))]",
|
||||||
|
"[resourceId('Microsoft.Sql/servers', variables('sqlServer'))]"
|
||||||
|
],
|
||||||
|
"type": "Microsoft.Network/privateDnsZones/TXT",
|
||||||
|
"apiVersion": "2018-09-01",
|
||||||
|
"name": "[concat(variables('privateDns'), '/laboratory')]",
|
||||||
|
"properties": {
|
||||||
|
"ttl": 30,
|
||||||
|
"txtRecords": [
|
||||||
|
{
|
||||||
|
"value": [
|
||||||
|
"[concat('clientId=', reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('identity'))).clientId)]"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": [
|
||||||
|
"[concat('identity=', variables('identity'))]"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": [
|
||||||
|
"[concat('runsContainer=', variables('runsContainer'))]"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": [
|
||||||
|
"[concat('runsQueueEndpoint=', concat(reference(resourceId('Microsoft.Storage/storageAccounts', variables('metadataStorage'))).primaryEndpoints.queue, variables('runsQueue')))]"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": [
|
||||||
|
"[concat('sqlDatabase=', variables('sqlDatabase'))]"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": [
|
||||||
|
"[concat('sqlServer=', reference(resourceId('Microsoft.Sql/servers', variables('sqlServer'))).fullyQualifiedDomainName)]"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": [
|
||||||
|
"[concat('storageAccount=', variables('metadataStorage'))]"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": [
|
||||||
|
"[concat('registry=', reference(resourceId('Microsoft.ContainerRegistry/registries', variables('registry'))).loginServer)]"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outputs": {
|
||||||
|
"registryId": {
|
||||||
|
"type": "string",
|
||||||
|
"value": "[resourceId('Microsoft.ContainerRegistry/registries', variables('registry'))]"
|
||||||
|
},
|
||||||
|
"siteId": {
|
||||||
|
"type": "string",
|
||||||
|
"value": "[resourceId('Microsoft.Web/sites', variables('site'))]"
|
||||||
|
},
|
||||||
|
"sqlServerId": {
|
||||||
|
"type": "string",
|
||||||
|
"value": "[resourceId('Microsoft.Sql/servers', variables('sqlServer'))]"
|
||||||
|
},
|
||||||
|
"storageAccountId": {
|
||||||
|
"type": "string",
|
||||||
|
"value": "[resourceId('Microsoft.Storage/storageAccounts', variables('metadataStorage'))]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
|
||||||
|
"contentVersion": "1.0.0.0",
|
||||||
|
"parameters": {
|
||||||
|
"baseName": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "dct"
|
||||||
|
},
|
||||||
|
"laboratorySiteId": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": {
|
||||||
|
"appInsights": "[concat(variables('prefix'), '-insights')]",
|
||||||
|
"prefix": "[toLower(concat(parameters('baseName'), take(uniqueString(resourceGroup().id), 6)))]",
|
||||||
|
"logAnalytics": "[concat(variables('prefix'), '-logs')]"
|
||||||
|
},
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"type": "Microsoft.Insights/components",
|
||||||
|
"apiVersion": "2015-05-01",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"name": "[variables('appInsights')]",
|
||||||
|
"kind": "web",
|
||||||
|
"tags": {
|
||||||
|
"[concat('hidden-link:', parameters('laboratorySiteId'))]": "Resource"
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"Application_Type": "web"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Microsoft.OperationalInsights/workspaces",
|
||||||
|
"apiVersion": "2015-11-01-preview",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"name": "[variables('logAnalytics')]",
|
||||||
|
"properties": {
|
||||||
|
"sku": {
|
||||||
|
"name": "PerGB2018"
|
||||||
|
},
|
||||||
|
"features": {
|
||||||
|
"enableLogAccessUsingOnlyResourcePermissions": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,330 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
|
||||||
|
"contentVersion": "1.0.0.0",
|
||||||
|
"parameters": {
|
||||||
|
},
|
||||||
|
"variables": {
|
||||||
|
"bootstrapAsg": "bootstrap",
|
||||||
|
"bootstrapSubnet": "bootstrap",
|
||||||
|
"bootstrapSubnetPrefix": "10.0.0.16/28",
|
||||||
|
"privateDns": "environment.private",
|
||||||
|
"paasSubnet": "paas",
|
||||||
|
"paasSubnetPrefix": "10.0.0.0/28",
|
||||||
|
"laboratorySubnet": "laboratory",
|
||||||
|
"laboratorySubnetPrefix": "10.0.0.32/27",
|
||||||
|
"lockdownSubnet": "lockdown",
|
||||||
|
"lockdownSubnetPrefix": "10.0.0.64/27",
|
||||||
|
"vnet": "environment",
|
||||||
|
"workerAsg": "worker"
|
||||||
|
},
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"type": "Microsoft.Network/applicationSecurityGroups",
|
||||||
|
"apiVersion": "2019-11-01",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"name": "[variables('workerAsg')]",
|
||||||
|
"properties": {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Microsoft.Network/applicationSecurityGroups",
|
||||||
|
"apiVersion": "2019-11-01",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"name": "[variables('bootstrapAsg')]",
|
||||||
|
"properties": {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Microsoft.Network/networkSecurityGroups",
|
||||||
|
"apiVersion": "2019-11-01",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"name": "[variables('bootstrapSubnet')]",
|
||||||
|
"properties": {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.Network/applicationSecurityGroups', variables('bootstrapAsg'))]",
|
||||||
|
"[resourceId('Microsoft.Network/applicationSecurityGroups', variables('workerAsg'))]"
|
||||||
|
],
|
||||||
|
"type": "Microsoft.Network/networkSecurityGroups",
|
||||||
|
"apiVersion": "2019-11-01",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"name": "[variables('paasSubnet')]",
|
||||||
|
"properties": {
|
||||||
|
"securityRules": [
|
||||||
|
{
|
||||||
|
"name": "all-inbound-deny",
|
||||||
|
"properties": {
|
||||||
|
"priority": 4096,
|
||||||
|
"direction": "Inbound",
|
||||||
|
"access": "Deny",
|
||||||
|
"protocol": "*",
|
||||||
|
"sourceAddressPrefix": "*",
|
||||||
|
"sourcePortRange": "*",
|
||||||
|
"destinationAddressPrefix": "*",
|
||||||
|
"destinationPortRange": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "worker-inbound-allow",
|
||||||
|
"properties": {
|
||||||
|
"priority": 1000,
|
||||||
|
"direction": "Inbound",
|
||||||
|
"access": "Allow",
|
||||||
|
"protocol": "TCP",
|
||||||
|
"sourceApplicationSecurityGroups": [
|
||||||
|
{
|
||||||
|
"id": "[resourceId('Microsoft.Network/applicationSecurityGroups', variables('workerAsg'))]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"sourcePortRange": "*",
|
||||||
|
"destinationAddressPrefix": "[variables('paasSubnetPrefix')]",
|
||||||
|
"destinationPortRange": "443"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "bootstrap-inbound-allow",
|
||||||
|
"properties": {
|
||||||
|
"priority": 1200,
|
||||||
|
"direction": "Inbound",
|
||||||
|
"access": "Allow",
|
||||||
|
"protocol": "TCP",
|
||||||
|
"sourceApplicationSecurityGroups": [
|
||||||
|
{
|
||||||
|
"id": "[resourceId('Microsoft.Network/applicationSecurityGroups', variables('bootstrapAsg'))]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"sourcePortRange": "*",
|
||||||
|
"destinationAddressPrefix": "[variables('paasSubnetPrefix')]",
|
||||||
|
"destinationPortRanges": [
|
||||||
|
"1433",
|
||||||
|
"443"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "all-outbound-deny",
|
||||||
|
"properties": {
|
||||||
|
"priority": 4096,
|
||||||
|
"direction": "Outbound",
|
||||||
|
"access": "Deny",
|
||||||
|
"protocol": "*",
|
||||||
|
"sourceAddressPrefix": "*",
|
||||||
|
"sourcePortRange": "*",
|
||||||
|
"destinationAddressPrefix": "*",
|
||||||
|
"destinationPortRange": "*"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Microsoft.Network/networkSecurityGroups",
|
||||||
|
"apiVersion": "2019-11-01",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"name": "[variables('laboratorySubnet')]",
|
||||||
|
"properties": {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.Network/applicationSecurityGroups', variables('workerAsg'))]"
|
||||||
|
],
|
||||||
|
"type": "Microsoft.Network/networkSecurityGroups",
|
||||||
|
"apiVersion": "2019-11-01",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"name": "[variables('lockdownSubnet')]",
|
||||||
|
"properties": {
|
||||||
|
"securityRules": [
|
||||||
|
{
|
||||||
|
"name": "all-inbound-deny",
|
||||||
|
"properties": {
|
||||||
|
"priority": 4096,
|
||||||
|
"direction": "Inbound",
|
||||||
|
"access": "Deny",
|
||||||
|
"protocol": "*",
|
||||||
|
"sourceAddressPrefix": "*",
|
||||||
|
"sourcePortRange": "*",
|
||||||
|
"destinationAddressPrefix": "*",
|
||||||
|
"destinationPortRange": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "private-endpoints-outbound-allow",
|
||||||
|
"properties": {
|
||||||
|
"priority": 1000,
|
||||||
|
"direction": "Outbound",
|
||||||
|
"access": "Allow",
|
||||||
|
"protocol": "TCP",
|
||||||
|
"sourceApplicationSecurityGroups": [
|
||||||
|
{
|
||||||
|
"id": "[resourceId('Microsoft.Network/applicationSecurityGroups', variables('workerAsg'))]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"sourcePortRange": "*",
|
||||||
|
"destinationAddressPrefix": "[variables('paasSubnetPrefix')]",
|
||||||
|
"destinationPortRange": "443"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "all-outbound-deny",
|
||||||
|
"properties": {
|
||||||
|
"priority": 4096,
|
||||||
|
"direction": "Outbound",
|
||||||
|
"access": "Deny",
|
||||||
|
"protocol": "*",
|
||||||
|
"sourceAddressPrefix": "*",
|
||||||
|
"sourcePortRange": "*",
|
||||||
|
"destinationAddressPrefix": "*",
|
||||||
|
"destinationPortRange": "*"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.Network/networkSecurityGroups', variables('bootstrapSubnet'))]",
|
||||||
|
"[resourceId('Microsoft.Network/networkSecurityGroups', variables('paasSubnet'))]",
|
||||||
|
"[resourceId('Microsoft.Network/networkSecurityGroups', variables('laboratorySubnet'))]",
|
||||||
|
"[resourceId('Microsoft.Network/networkSecurityGroups', variables('lockdownSubnet'))]"
|
||||||
|
],
|
||||||
|
"type": "Microsoft.Network/virtualNetworks",
|
||||||
|
"apiVersion": "2019-11-01",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"name": "[variables('vnet')]",
|
||||||
|
"properties": {
|
||||||
|
"addressSpace": {
|
||||||
|
"addressPrefixes": [
|
||||||
|
"10.0.0.0/24"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"subnets": [
|
||||||
|
{
|
||||||
|
"name": "[variables('paasSubnet')]",
|
||||||
|
"properties": {
|
||||||
|
"addressPrefix": "[variables('paasSubnetPrefix')]",
|
||||||
|
"networkSecurityGroup": {
|
||||||
|
"id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('paasSubnet'))]"
|
||||||
|
},
|
||||||
|
"privateEndpointNetworkPolicies": "Disabled"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "[variables('bootstrapSubnet')]",
|
||||||
|
"properties": {
|
||||||
|
"addressPrefix": "[variables('bootstrapSubnetPrefix')]",
|
||||||
|
"networkSecurityGroup": {
|
||||||
|
"id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('bootstrapSubnet'))]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "[variables('laboratorySubnet')]",
|
||||||
|
"properties": {
|
||||||
|
"addressPrefix": "[variables('laboratorySubnetPrefix')]",
|
||||||
|
"delegations": [
|
||||||
|
{
|
||||||
|
"name": "appService",
|
||||||
|
"properties": {
|
||||||
|
"serviceName": "Microsoft.Web/serverfarms"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"networkSecurityGroup": {
|
||||||
|
"id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('laboratorySubnet'))]"
|
||||||
|
},
|
||||||
|
"serviceEndpoints": [
|
||||||
|
{
|
||||||
|
"service": "Microsoft.Sql",
|
||||||
|
"locations": [
|
||||||
|
"[resourceGroup().location]"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"service": "Microsoft.Storage",
|
||||||
|
"locations": [
|
||||||
|
"[resourceGroup().location]"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "[variables('lockdownSubnet')]",
|
||||||
|
"properties": {
|
||||||
|
"addressPrefix": "[variables('lockdownSubnetPrefix')]",
|
||||||
|
"networkSecurityGroup": {
|
||||||
|
"id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('lockdownSubnet'))]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.Network/virtualNetworks', variables('vnet'))]"
|
||||||
|
],
|
||||||
|
"type": "Microsoft.Network/privateDnsZones",
|
||||||
|
"apiVersion": "2018-09-01",
|
||||||
|
"location": "global",
|
||||||
|
"name": "[variables('privateDns')]",
|
||||||
|
"properties": {
|
||||||
|
},
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.Network/privateDnsZones', variables('privateDns'))]"
|
||||||
|
],
|
||||||
|
"type": "virtualNetworkLinks",
|
||||||
|
"apiVersion": "2018-09-01",
|
||||||
|
"location": "global",
|
||||||
|
"name": "privatedns",
|
||||||
|
"properties": {
|
||||||
|
"registrationEnabled": false,
|
||||||
|
"virtualNetwork": {
|
||||||
|
"id": "[resourceId('Microsoft.Network/virtualNetworks', variables('vnet'))]",
|
||||||
|
"resourceGroup": "[resourceGroup().name]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outputs": {
|
||||||
|
"bootstrapAsgId": {
|
||||||
|
"type": "string",
|
||||||
|
"value": "[resourceId('Microsoft.Network/applicationSecurityGroups', variables('bootstrapAsg'))]"
|
||||||
|
},
|
||||||
|
"bootstrapSubnetId": {
|
||||||
|
"type": "string",
|
||||||
|
"value": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('vnet'), variables('bootstrapSubnet'))]"
|
||||||
|
},
|
||||||
|
"paasSubnetId": {
|
||||||
|
"type": "string",
|
||||||
|
"value": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('vnet'), variables('paasSubnet'))]"
|
||||||
|
},
|
||||||
|
"laboratorySubnetId": {
|
||||||
|
"type": "string",
|
||||||
|
"value": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('vnet'), variables('laboratorySubnet'))]"
|
||||||
|
},
|
||||||
|
"lockdownSubnetId": {
|
||||||
|
"type": "string",
|
||||||
|
"value": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('vnet'), variables('lockdownSubnet'))]"
|
||||||
|
},
|
||||||
|
"privateDnsId": {
|
||||||
|
"type": "string",
|
||||||
|
"value": "[resourceId('Microsoft.Network/privateDnsZones', variables('privateDns'))]"
|
||||||
|
},
|
||||||
|
"vnetId": {
|
||||||
|
"type": "string",
|
||||||
|
"value": "[resourceId('Microsoft.Network/virtualNetworks', variables('vnet'))]"
|
||||||
|
},
|
||||||
|
"workerAsgId": {
|
||||||
|
"type": "string",
|
||||||
|
"value": "[resourceId('Microsoft.Network/applicationSecurityGroups', variables('workerAsg'))]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,220 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
|
||||||
|
"contentVersion": "1.0.0.0",
|
||||||
|
"parameters": {
|
||||||
|
"laboratoryRegistryId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"laboratorySqlServerId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"laboratoryStorageAccountId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"subnetId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"vnetId": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": {
|
||||||
|
"laboratoryRegistry": "[last(split(parameters('laboratoryRegistryId'), '/'))]",
|
||||||
|
"laboratorySqlServer": "[last(split(parameters('laboratorySqlServerId'), '/'))]",
|
||||||
|
"laboratoryStorageAccount": "[last(split(parameters('laboratoryStorageAccountId'), '/'))]",
|
||||||
|
"privateDnsZones": [
|
||||||
|
"privatelink.blob.core.windows.net",
|
||||||
|
"privatelink.queue.core.windows.net",
|
||||||
|
"privatelink.database.windows.net",
|
||||||
|
"privatelink.azurecr.io"
|
||||||
|
],
|
||||||
|
"privateEndpoints": [
|
||||||
|
{
|
||||||
|
"name": "laboratory-blob",
|
||||||
|
"dnsZone": "privatelink.blob.core.windows.net",
|
||||||
|
"dnsNames": [
|
||||||
|
"[variables('laboratoryStorageAccount')]"
|
||||||
|
],
|
||||||
|
"groupIds": [
|
||||||
|
"blob"
|
||||||
|
],
|
||||||
|
"resourceId": "[parameters('laboratoryStorageAccountId')]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "laboratory-queue",
|
||||||
|
"dnsZone": "privatelink.queue.core.windows.net",
|
||||||
|
"dnsNames": [
|
||||||
|
"[variables('laboratoryStorageAccount')]"
|
||||||
|
],
|
||||||
|
"groupIds": [
|
||||||
|
"queue"
|
||||||
|
],
|
||||||
|
"resourceId": "[parameters('laboratoryStorageAccountId')]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "laboratory-sql",
|
||||||
|
"dnsZone": "privatelink.database.windows.net",
|
||||||
|
"dnsNames": [
|
||||||
|
"[variables('laboratorySqlServer')]"
|
||||||
|
],
|
||||||
|
"groupIds": [
|
||||||
|
"sqlServer"
|
||||||
|
],
|
||||||
|
"resourceId": "[parameters('laboratorySqlServerId')]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "laboratory-acr",
|
||||||
|
"dnsZone": "privatelink.azurecr.io",
|
||||||
|
"dnsNames": [
|
||||||
|
"[format('{0}.{1}.data', variables('laboratoryRegistry'), tolower(resourceGroup().location))]",
|
||||||
|
"[variables('laboratoryRegistry')]"
|
||||||
|
],
|
||||||
|
"groupIds": [
|
||||||
|
"registry"
|
||||||
|
],
|
||||||
|
"resourceId": "[parameters('laboratoryRegistryId')]"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"copy": {
|
||||||
|
"name": "privateEndpoints",
|
||||||
|
"count": "[length(variables('privateEndpoints'))]"
|
||||||
|
},
|
||||||
|
"type": "Microsoft.Network/privateEndpoints",
|
||||||
|
"apiVersion": "2019-11-01",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"name": "[variables('privateEndpoints')[copyIndex()].name]",
|
||||||
|
"properties": {
|
||||||
|
"privateLinkServiceConnections": [
|
||||||
|
{
|
||||||
|
"name": "[variables('privateEndpoints')[copyIndex()].name]",
|
||||||
|
"properties": {
|
||||||
|
"groupIds": "[variables('privateEndpoints')[copyIndex()].groupIds]",
|
||||||
|
"privateLinkServiceId": "[variables('privateEndpoints')[copyIndex()].resourceId]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"subnet": {
|
||||||
|
"id": "[parameters('subnetId')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"copy": {
|
||||||
|
"name": "privateDnsZones",
|
||||||
|
"count": "[length(variables('privateDnsZones'))]"
|
||||||
|
},
|
||||||
|
"type": "Microsoft.Network/privateDnsZones",
|
||||||
|
"apiVersion": "2018-09-01",
|
||||||
|
"location": "global",
|
||||||
|
"name": "[variables('privateDnsZones')[copyIndex()]]",
|
||||||
|
"properties": {
|
||||||
|
},
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.Network/privateDnsZones', variables('privateDnsZones')[copyIndex()])]"
|
||||||
|
],
|
||||||
|
"type": "SOA",
|
||||||
|
"apiVersion": "2018-09-01",
|
||||||
|
"name": "@",
|
||||||
|
"properties": {
|
||||||
|
"ttl": 3600,
|
||||||
|
"soaRecord": {
|
||||||
|
"email": "azureprivatedns-host.microsoft.com",
|
||||||
|
"expireTime": 2419200,
|
||||||
|
"host": "azureprivatedns.net",
|
||||||
|
"refreshTime": 3600,
|
||||||
|
"retryTime": 300,
|
||||||
|
"serialNumber": 1,
|
||||||
|
"minimumTtl": 300
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.Network/privateDnsZones', variables('privateDnsZones')[copyIndex()])]"
|
||||||
|
],
|
||||||
|
"type": "virtualNetworkLinks",
|
||||||
|
"apiVersion": "2018-09-01",
|
||||||
|
"location": "global",
|
||||||
|
"name": "privatedns",
|
||||||
|
"properties": {
|
||||||
|
"registrationEnabled": false,
|
||||||
|
"virtualNetwork": {
|
||||||
|
"id": "[parameters('vnetId')]",
|
||||||
|
"resourceGroup": "[resourceGroup().name]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"copy": {
|
||||||
|
"name": "privateDnsRecords",
|
||||||
|
"count": "[length(variables('privateEndpoints'))]"
|
||||||
|
},
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.Network/privateDnsZones', variables('privateEndpoints')[copyIndex()].dnsZone)]",
|
||||||
|
"[resourceId('Microsoft.Network/privateEndpoints', variables('privateEndpoints')[copyIndex()].name)]"
|
||||||
|
],
|
||||||
|
"type": "Microsoft.Resources/deployments",
|
||||||
|
"apiVersion": "2017-05-10",
|
||||||
|
"name": "[concat('private-dns-', variables('privateEndpoints')[copyIndex()].name)]",
|
||||||
|
"resourceGroup": "[resourceGroup().name]",
|
||||||
|
"properties": {
|
||||||
|
"mode": "Incremental",
|
||||||
|
"expressionEvaluationOptions": {
|
||||||
|
"scope": "inner"
|
||||||
|
},
|
||||||
|
"parameters": {
|
||||||
|
"privateDnsZoneName": {
|
||||||
|
"value": "[variables('privateEndpoints')[copyIndex()].dnsZone]"
|
||||||
|
},
|
||||||
|
"endpointNicId": {
|
||||||
|
"value": "[reference(resourceId('Microsoft.Network/privateEndpoints', variables('privateEndpoints')[copyIndex()].name)).networkInterfaces[0].id]"
|
||||||
|
},
|
||||||
|
"endpointDnsNames": {
|
||||||
|
"value": "[variables('privateEndpoints')[copyIndex()].dnsNames]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"template": {
|
||||||
|
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
|
||||||
|
"contentVersion": "1.0.0.0",
|
||||||
|
"parameters": {
|
||||||
|
"privateDnsZoneName": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"endpointNicId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"endpointDnsNames": {
|
||||||
|
"type": "array"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"copy": {
|
||||||
|
"name": "endpointDnsName",
|
||||||
|
"count": "[length(parameters('endpointDnsNames'))]"
|
||||||
|
},
|
||||||
|
"type": "Microsoft.Network/privateDnsZones/A",
|
||||||
|
"apiVersion": "2018-09-01",
|
||||||
|
"name": "[concat(parameters('privateDnsZoneName'), '/', parameters('endpointDnsNames')[copyIndex()])]",
|
||||||
|
"properties": {
|
||||||
|
"ttl": 3600,
|
||||||
|
"aRecords": [
|
||||||
|
{
|
||||||
|
"ipv4Address": "[reference(parameters('endpointNicId'), '2019-11-01').ipConfigurations[copyIndex()].properties.privateIPAddress]"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
|
||||||
|
"contentVersion": "1.0.0.0",
|
||||||
|
"resources": [
|
||||||
|
],
|
||||||
|
"outputs": {
|
||||||
|
"templateLinkUri": {
|
||||||
|
"type": "string",
|
||||||
|
"value": "[if(contains(deployment().properties, 'templateLink'), deployment().properties.templateLink.uri, 'ERROR: templateLink does not exist!')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,102 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
|
||||||
|
"contentVersion": "1.0.0.0",
|
||||||
|
"parameters": {
|
||||||
|
"asgId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"identityId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"subnetId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"imageId": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "[resourceId('Microsoft.Compute/images', 'dct-worker')]"
|
||||||
|
},
|
||||||
|
"vmPassword": {
|
||||||
|
"type": "securestring",
|
||||||
|
"defaultValue": "[newGuid()]"
|
||||||
|
},
|
||||||
|
"vmSize": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "Standard_DS2_v2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": {
|
||||||
|
"name": "worker"
|
||||||
|
},
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"type": "Microsoft.Network/networkInterfaces",
|
||||||
|
"apiVersion": "2019-11-01",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"name": "[variables('name')]",
|
||||||
|
"properties": {
|
||||||
|
"ipConfigurations": [
|
||||||
|
{
|
||||||
|
"name": "default",
|
||||||
|
"properties": {
|
||||||
|
"applicationSecurityGroups": [
|
||||||
|
{
|
||||||
|
"id": "[parameters('asgId')]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"privateIPAllocationMethod": "Dynamic",
|
||||||
|
"subnet": {
|
||||||
|
"id": "[parameters('subnetId')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dependsOn": [
|
||||||
|
"[resourceId('Microsoft.Network/networkInterfaces', variables('name'))]"
|
||||||
|
],
|
||||||
|
"type": "Microsoft.Compute/virtualMachines",
|
||||||
|
"apiVersion": "2019-07-01",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"name": "[variables('name')]",
|
||||||
|
"identity": {
|
||||||
|
"type": "UserAssigned",
|
||||||
|
"userAssignedIdentities": {
|
||||||
|
"[parameters('identityId')]": {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"hardwareProfile": {
|
||||||
|
"vmSize": "[parameters('vmSize')]"
|
||||||
|
},
|
||||||
|
"networkProfile": {
|
||||||
|
"networkInterfaces": [
|
||||||
|
{
|
||||||
|
"id": "[resourceId('Microsoft.Network/networkInterfaces', variables('name'))]"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"osProfile": {
|
||||||
|
"adminUsername": "azureuser",
|
||||||
|
"adminPassword": "[parameters('vmPassword')]",
|
||||||
|
"computerName": "[variables('name')]",
|
||||||
|
"linuxConfiguration": {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"storageProfile": {
|
||||||
|
"imageReference": {
|
||||||
|
"id": "[parameters('imageId')]"
|
||||||
|
},
|
||||||
|
"osDisk": {
|
||||||
|
"createOption": "FromImage",
|
||||||
|
"managedDisk": {
|
||||||
|
"storageAccountType": "Premium_LRS"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
#!/usr/bin/env pwsh
|
||||||
|
$ErrorActionPreference='Stop'
|
||||||
|
|
||||||
|
# Retrieve settings from DNS TXT record
|
||||||
|
$settings = @{}
|
||||||
|
$(dig '@168.63.129.16' +short laboratory.environment.private txt).Split("\n") | % {
|
||||||
|
$parts = $_.Substring(1, $_.Length-2)
|
||||||
|
$delimiter = $parts.IndexOf("=")
|
||||||
|
$key = $parts.Substring(0, $delimiter)
|
||||||
|
$value = $parts.Substring($delimiter + 1)
|
||||||
|
$settings[$key] = $value
|
||||||
|
}
|
||||||
|
|
||||||
|
$server = $settings["sqlServer"]
|
||||||
|
$database = $settings["sqlDatabase"]
|
||||||
|
$identity = $settings["identity"]
|
||||||
|
$clientId = $settings["clientId"]
|
||||||
|
$storageAccount = $settings["storageAccount"]
|
||||||
|
|
||||||
|
$settings["runsQueueEndpoint"] -match 'https://(?<storageAccount>\w+)\..*/(?<queue>\w+)'
|
||||||
|
$runsQueueStorageAccount = $matches["storageAccount"]
|
||||||
|
$runsQueue = $matches["queue"]
|
||||||
|
|
||||||
|
# Configure storage
|
||||||
|
az storage queue create --auth-mode login --account-name $runsQueueStorageAccount -n $runsQueue
|
||||||
|
if ($LastExitCode -ne 0) {
|
||||||
|
exit $LastExitCode
|
||||||
|
}
|
||||||
|
|
||||||
|
# Connect to Azure SQL via AAD (Managed Identity)
|
||||||
|
$token = curl -s 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://database.windows.net/' -H 'Metadata: true' | ConvertFrom-Json;
|
||||||
|
$conn = New-Object System.Data.SqlClient.SqlConnection;
|
||||||
|
$conn.ConnectionString = "Data Source=$server; Initial Catalog=$database;";
|
||||||
|
$conn.AccessToken = $token.access_token;
|
||||||
|
$conn.Open()
|
||||||
|
Write-Output "Connected to $server/$database using Managed Identity"
|
||||||
|
|
||||||
|
# Grant AAD permissions in Azure SQL
|
||||||
|
foreach ($byte in [System.Guid]::Parse($clientId).ToByteArray()) { $byteGuid += [System.String]::Format("{0:X2}", $byte) }
|
||||||
|
$sql = @"
|
||||||
|
if not exists (select name from sys.database_principals where name = '$identity')
|
||||||
|
begin
|
||||||
|
create user [$identity] with default_schema=[dbo], SID=0x$byteGuid, TYPE=E;
|
||||||
|
end
|
||||||
|
|
||||||
|
alter role db_ddladmin add member [$identity];
|
||||||
|
alter role db_datareader add member [$identity];
|
||||||
|
alter role db_datawriter add member [$identity];
|
||||||
|
"@
|
||||||
|
$cmd = New-Object System.Data.SqlClient.SqlCommand($sql, $conn)
|
||||||
|
$cmd.ExecuteNonQuery()
|
||||||
|
Write-Output "Added $identity as an AAD user to $server/$database"
|
||||||
|
|
||||||
|
$conn.Close()
|
||||||
|
|
||||||
|
# Deallocate bootstrap VM (self)
|
||||||
|
$vmId = $(curl -s 'http://169.254.169.254/metadata/instance/compute/resourceId?api-version=2019-08-15&format=text' -H 'Metadata: true')
|
||||||
|
az vm deallocate --no-wait --ids $vmId
|
|
@ -0,0 +1,14 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -euxo pipefail
|
||||||
|
|
||||||
|
# Repositories
|
||||||
|
curl -fsSL https://packages.microsoft.com/keys/microsoft.asc | apt-key add -
|
||||||
|
apt-add-repository "deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ $(lsb_release -cs) main"
|
||||||
|
apt-add-repository "deb [arch=amd64] https://packages.microsoft.com/ubuntu/$(lsb_release -rs)/prod $(lsb_release -cs) main"
|
||||||
|
|
||||||
|
# Install tools
|
||||||
|
apt-get update -y
|
||||||
|
apt-get install -y azure-cli powershell
|
||||||
|
|
||||||
|
# Configure storage
|
||||||
|
az login --identity --allow-no-subscriptions
|
|
@ -0,0 +1,112 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -eo pipefail
|
||||||
|
|
||||||
|
show_usage() {
|
||||||
|
echo 'Usage: deploy.sh -g <resource_group> [--assets <assets_base_uri>] [--dev] [--force]'
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_arguments() {
|
||||||
|
PARAMS=""
|
||||||
|
while (( $# )); do
|
||||||
|
case "$1" in
|
||||||
|
-h|--help)
|
||||||
|
show_usage
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
-f|--force)
|
||||||
|
FORCE=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-g|--resource-group)
|
||||||
|
RESOURCE_GROUP=$2
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-a|--assets)
|
||||||
|
ASSETS_BASE=$2
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--dev)
|
||||||
|
DEV=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--)
|
||||||
|
shift
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
-*|--*)
|
||||||
|
echo "Unsupported flag $1" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
PARAMS="$PARAMS $1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
validate_arguments() {
|
||||||
|
if [[ -z "$RESOURCE_GROUP" ]]; then
|
||||||
|
show_usage
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$ASSETS_BASE" && "$DEV" = true ]]; then
|
||||||
|
ASSETS_BASE=$(curl -s http://127.0.0.1:4040/api/tunnels | jq -r '.tunnels[] | select(.name == "deploy").public_url')
|
||||||
|
fi
|
||||||
|
|
||||||
|
ASSETS_BASE=${ASSETS_BASE:-'https://raw.githubusercontent.com/microsoft/data-contest-toolkit/master/deploy'}
|
||||||
|
FORCE=${FORCE:-false}
|
||||||
|
}
|
||||||
|
|
||||||
|
deploy_environment() {
|
||||||
|
if ! az image show -g $RESOURCE_GROUP -n dct-worker &>/dev/null || [ "$FORCE" = true ]; then
|
||||||
|
TMP_DIR=$(mktemp -d)
|
||||||
|
(
|
||||||
|
pushd $TMP_DIR
|
||||||
|
curl -sL -O "${ASSETS_BASE}/worker/packer.json" -O "${ASSETS_BASE}/worker/setup.sh" -O "${ASSETS_BASE}/worker/start.sh"
|
||||||
|
packer build -force -var resource_group=$RESOURCE_GROUP packer.json
|
||||||
|
)
|
||||||
|
else
|
||||||
|
>&2 echo "Skipping worker VM image. Run with --force to recreate"
|
||||||
|
fi
|
||||||
|
|
||||||
|
az deployment group create -g $RESOURCE_GROUP -u "${ASSETS_BASE}/azure/azuredeploy.json" -p "assetsBaseUrl=$ASSETS_BASE"
|
||||||
|
}
|
||||||
|
|
||||||
|
deploy_laboratory() {
|
||||||
|
SITE_ID=$(az deployment group show -g $RESOURCE_GROUP -n azuredeploy --query properties.outputs.laboratorySiteId.value -o tsv)
|
||||||
|
|
||||||
|
npm run laboratory:package:appservice
|
||||||
|
az webapp deployment source config-zip --ids $SITE_ID --src dist/data-contest-toolkit.zip
|
||||||
|
az webapp restart --ids $SITE_ID
|
||||||
|
}
|
||||||
|
|
||||||
|
deploy_worker() {
|
||||||
|
REGISTRY=$(az deployment group show -g $RESOURCE_GROUP -n azuredeploy --query properties.outputs.laboratoryRegistryName.value -o tsv)
|
||||||
|
|
||||||
|
az acr import -n $REGISTRY --source docker.io/acanthamoeba/dct-worker:latest -t worker:latest --force
|
||||||
|
}
|
||||||
|
|
||||||
|
deploy_dev() {
|
||||||
|
if [ "$DEV" = true ]; then
|
||||||
|
az vm wait -g $RESOURCE_GROUP -n bootstrap --custom "instanceView.statuses[?code=='PowerState/deallocated']"
|
||||||
|
az vm start -g $RESOURCE_GROUP -n bootstrap
|
||||||
|
az deployment group create -g $RESOURCE_GROUP -u "${ASSETS_BASE}/azure/dev.json" -p "sshPublicKey=$(cat ~/.ssh/id_rsa.pub)"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_arguments "$@"
|
||||||
|
validate_arguments
|
||||||
|
|
||||||
|
if [ -f .env ]; then
|
||||||
|
set -o allexport
|
||||||
|
source .env
|
||||||
|
set +o allexport
|
||||||
|
fi
|
||||||
|
|
||||||
|
set -ux
|
||||||
|
deploy_environment
|
||||||
|
deploy_worker
|
||||||
|
deploy_laboratory
|
||||||
|
deploy_dev
|
|
@ -0,0 +1,55 @@
|
||||||
|
{
|
||||||
|
"variables": {
|
||||||
|
"name": "dct-worker",
|
||||||
|
"resource_group": null,
|
||||||
|
|
||||||
|
"tenant_id": "{{env `AZURE_TENANT_ID`}}",
|
||||||
|
"subscription_id": "{{env `AZURE_SUBSCRIPTION_ID`}}",
|
||||||
|
"client_id": "{{env `AZURE_CLIENT_ID`}}",
|
||||||
|
"client_secret": "{{env `AZURE_CLIENT_SECRET`}}",
|
||||||
|
"location": "southcentralus"
|
||||||
|
},
|
||||||
|
"sensitive-variables": [
|
||||||
|
"client_secret"
|
||||||
|
],
|
||||||
|
"builders": [
|
||||||
|
{
|
||||||
|
"type": "azure-arm",
|
||||||
|
"async_resourcegroup_delete": true,
|
||||||
|
|
||||||
|
"tenant_id": "{{user `tenant_id`}}",
|
||||||
|
"subscription_id": "{{user `subscription_id`}}",
|
||||||
|
"client_id": "{{user `client_id`}}",
|
||||||
|
"client_secret": "{{user `client_secret`}}",
|
||||||
|
"location": "{{user `location`}}",
|
||||||
|
|
||||||
|
"os_type": "Linux",
|
||||||
|
"image_publisher": "Canonical",
|
||||||
|
"image_offer": "UbuntuServer",
|
||||||
|
"image_sku": "18.04-LTS",
|
||||||
|
|
||||||
|
"managed_image_name": "{{user `name`}}",
|
||||||
|
"managed_image_resource_group_name": "{{user `resource_group`}}"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"provisioners": [
|
||||||
|
{
|
||||||
|
"type": "file",
|
||||||
|
"source": "{{template_dir}}/start.sh",
|
||||||
|
"destination": "/tmp/start.sh"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "shell",
|
||||||
|
"execute_command": "chmod +x {{ .Path }}; {{ .Vars }} sudo -E bash '{{ .Path }}'",
|
||||||
|
"script": "{{template_dir}}/setup.sh"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "shell",
|
||||||
|
"execute_command": "chmod +x {{ .Path }}; {{ .Vars }} sudo -E sh '{{ .Path }}'",
|
||||||
|
"inline_shebang": "/bin/sh -x",
|
||||||
|
"inline": [
|
||||||
|
"/usr/sbin/waagent -force -deprovision+user && export HISTSIZE=0 && sync"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Docker repository
|
||||||
|
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
|
||||||
|
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
|
||||||
|
|
||||||
|
# Microsoft repository
|
||||||
|
curl -fsSL https://packages.microsoft.com/keys/microsoft.asc | apt-key add -
|
||||||
|
apt-add-repository "deb [arch=amd64] https://packages.microsoft.com/ubuntu/$(lsb_release -rs)/prod $(lsb_release -cs) main"
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
apt-get update -y
|
||||||
|
apt-get install -y jq docker-ce docker-ce-cli containerd.io blobfuse fuse
|
||||||
|
|
||||||
|
# Move startup script
|
||||||
|
chmod +x /tmp/start.sh
|
||||||
|
mv /tmp/start.sh /var/lib/cloud/scripts/per-boot/start.sh
|
|
@ -0,0 +1,36 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# service discovery via DNS
|
||||||
|
SETTINGS=$(dig @168.63.129.16 +short laboratory.environment.private txt)
|
||||||
|
|
||||||
|
# blobfuse: one-time setup
|
||||||
|
mkdir -p /mnt/blobfusetmp
|
||||||
|
|
||||||
|
# blobfuse: mount runs container
|
||||||
|
mkdir -p /var/dct/runs
|
||||||
|
|
||||||
|
export AZURE_STORAGE_ACCOUNT=$(grep -Po 'storageAccount=\K[^"]*' <<< $SETTINGS)
|
||||||
|
export AZURE_STORAGE_AUTH_TYPE=MSI
|
||||||
|
CONTAINER=$(grep -Po 'runsContainer=\K[^"]*' <<< $SETTINGS)
|
||||||
|
|
||||||
|
blobfuse /var/dct/runs --container-name=$CONTAINER --tmp-path=/mnt/blobfusetmp
|
||||||
|
|
||||||
|
# pull latest worker
|
||||||
|
AAD_ACCESS_TOKEN=$(curl -s -H 'Metadata: true' 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/' | jq -r '.access_token')
|
||||||
|
CLAIMS=$(echo $AAD_ACCESS_TOKEN | cut -d '.' -f 2)
|
||||||
|
TENANT=$(echo $CLAIMS | base64 -d | jq -r '.iss | capture("https://(.*)/(?<tenant>.*)/").tenant')
|
||||||
|
|
||||||
|
REGISTRY=$(grep -Po 'registry=\K\K[^"]*' <<< $SETTINGS)
|
||||||
|
ACR_REFRESH_TOKEN=$(curl -s -X POST -H 'Content-Type: application/x-www-form-urlencoded' -d "grant_type=access_token&service=$REGISTRY&tenant=$TENANT&access_token=$AAD_ACCESS_TOKEN" https://$REGISTRY/oauth2/exchange | jq -r '.refresh_token')
|
||||||
|
docker login -u 00000000-0000-0000-0000-000000000000 -p $ACR_REFRESH_TOKEN $REGISTRY
|
||||||
|
|
||||||
|
# If the pull was unsuccessful (not yet provisioned, network blip, etc), wait a bit and keep trying
|
||||||
|
while ! docker pull $REGISTRY/worker; do
|
||||||
|
sleep 10
|
||||||
|
done
|
||||||
|
|
||||||
|
# run worker app
|
||||||
|
QUEUE_ENDPOINT=$(grep -Po 'runsQueueEndpoint=\K[^"]*' <<< $SETTINGS)
|
||||||
|
docker container rm worker --force || true
|
||||||
|
docker container run -d --name worker --restart always -v /var/run/docker.sock:/var/run/docker.sock -e QUEUE_MODE=azure -e QUEUE_ENDPOINT=$QUEUE_ENDPOINT $REGISTRY/worker
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
48
package.json
48
package.json
|
@ -16,32 +16,35 @@
|
||||||
"posttest": "npm run check",
|
"posttest": "npm run check",
|
||||||
"laboratory": "node build/src/laboratory/server/main.js",
|
"laboratory": "node build/src/laboratory/server/main.js",
|
||||||
"laboratory:dev": "npm run compile && node -r dotenv/config build/src/laboratory/server/main.js",
|
"laboratory:dev": "npm run compile && node -r dotenv/config build/src/laboratory/server/main.js",
|
||||||
"laboratory:package:appservice": "npm run compile && mkdir -p dist && cp -r --parents package*.json build/src dist && cd dist && npm install --ignore-scripts --production && zip -r $npm_package_name.zip package.json package-lock.json build/src node_modules",
|
"prelaboratory:package:appservice": "rimraf ./dist",
|
||||||
|
"laboratory:package:appservice": "npm run compile && mkdir -p dist && cp -r --parents package*.json build/src dist && cd dist && npm install --ignore-scripts --only=prod && zip -r $npm_package_name.zip package.json package-lock.json build/src node_modules",
|
||||||
"sds": "node build/src/cli/sds.js",
|
"sds": "node build/src/cli/sds.js",
|
||||||
"sds:dev": "npm run compile && node -r dotenv/config build/src/cli/sds.js",
|
"sds:dev": "npm run compile && node -r dotenv/config build/src/cli/sds.js",
|
||||||
"worker": "node build/src/worker/app.js",
|
"worker": "node build/src/worker/app.js",
|
||||||
"worker:dev": "npm run compile && node -r dotenv/config build/src/worker/app.js"
|
"worker:dev": "npm run compile && node -r dotenv/config build/src/worker/app.js",
|
||||||
|
"preazure:dev": "serve -l 8080 deploy >/dev/null &",
|
||||||
|
"azure:dev": "ngrok start -config .ngrok.yml deploy",
|
||||||
|
"postazure:dev": "kill $(lsof -t -i:8080)"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@azure/identity": "^1.0.2",
|
"@azure/identity": "^1.0.3",
|
||||||
"@azure/storage-queue": "^12.0.4",
|
"@azure/storage-queue": "^12.0.4",
|
||||||
"axios": "^0.19.2",
|
"axios": "^0.19.2",
|
||||||
"body-parser": "^1.19.0",
|
"body-parser": "^1.19.0",
|
||||||
"commander": "^5.0.0",
|
"commander": "^5.1.0",
|
||||||
"dockerode": "^3.1.0",
|
"dockerode": "^3.2.0",
|
||||||
"dotenv": "^8.2.0",
|
"env-var": "^6.1.1",
|
||||||
"env-var": "^6.0.4",
|
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"fp-ts": "^2.5.3",
|
"fp-ts": "^2.5.4",
|
||||||
"io-ts": "^2.1.2",
|
"io-ts": "^2.2.2",
|
||||||
"js-yaml": "^3.13.1",
|
"js-yaml": "^3.13.1",
|
||||||
"luxon": "^1.22.2",
|
"luxon": "^1.24.1",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"sequelize": "^5.21.5",
|
"sequelize": "^5.21.7",
|
||||||
"sequelize-typescript": "^1.1.0",
|
"sequelize-typescript": "^1.1.0",
|
||||||
"sqlite3": "^4.1.1",
|
"sqlite3": "^4.2.0",
|
||||||
"strong-error-handler": "^3.4.0",
|
"strong-error-handler": "^3.4.0",
|
||||||
"tedious": "^8.2.0",
|
"tedious": "^8.3.0",
|
||||||
"uuid": "^3.4.0"
|
"uuid": "^3.4.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -52,31 +55,34 @@
|
||||||
"@types/chai": "^4.2.11",
|
"@types/chai": "^4.2.11",
|
||||||
"@types/chai-as-promised": "^7.1.2",
|
"@types/chai-as-promised": "^7.1.2",
|
||||||
"@types/chai-http": "^4.2.0",
|
"@types/chai-http": "^4.2.0",
|
||||||
"@types/dockerode": "^2.5.26",
|
"@types/dockerode": "^2.5.28",
|
||||||
"@types/dotenv": "^8.2.0",
|
"@types/dotenv": "^8.2.0",
|
||||||
"@types/express": "^4.17.3",
|
"@types/express": "^4.17.6",
|
||||||
"@types/js-yaml": "^3.12.3",
|
"@types/js-yaml": "^3.12.3",
|
||||||
"@types/luxon": "^1.22.0",
|
"@types/luxon": "^1.22.0",
|
||||||
"@types/mocha": "^7.0.2",
|
"@types/mocha": "^7.0.2",
|
||||||
"@types/nock": "^11.1.0",
|
"@types/nock": "^11.1.0",
|
||||||
"@types/node": "^12.12.31",
|
"@types/node": "^12.12.37",
|
||||||
"@types/request-promise": "^4.1.46",
|
"@types/request-promise": "^4.1.46",
|
||||||
"@types/sinon": "^7.5.2",
|
"@types/sinon": "^7.5.2",
|
||||||
"@types/sinonjs__fake-timers": "^6.0.0",
|
"@types/sinonjs__fake-timers": "^6.0.1",
|
||||||
"@types/tedious": "^4.0.0",
|
"@types/tedious": "^4.0.0",
|
||||||
"@types/uuid": "^3.4.7",
|
"@types/uuid": "^3.4.9",
|
||||||
"@types/validator": "^12.0.1",
|
"@types/validator": "^12.0.1",
|
||||||
"@types/yargs": "^15.0.4",
|
"@types/yargs": "^15.0.4",
|
||||||
"chai": "^4.2.0",
|
"chai": "^4.2.0",
|
||||||
"chai-as-promised": "^7.1.1",
|
"chai-as-promised": "^7.1.1",
|
||||||
"chai-exclude": "^2.0.2",
|
"chai-exclude": "^2.0.2",
|
||||||
"chai-http": "^4.3.0",
|
"chai-http": "^4.3.0",
|
||||||
|
"dotenv": "^8.2.0",
|
||||||
"gts": "^1.1.2",
|
"gts": "^1.1.2",
|
||||||
"mocha": "^7.1.1",
|
"mocha": "^7.1.2",
|
||||||
|
"ngrok": "^3.2.7",
|
||||||
"nock": "^12.0.3",
|
"nock": "^12.0.3",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"sinon": "^9.0.0",
|
"serve": "^11.3.0",
|
||||||
"source-map-support": "^0.5.16",
|
"sinon": "^9.0.2",
|
||||||
|
"source-map-support": "^0.5.19",
|
||||||
"typescript": "^3.8.3",
|
"typescript": "^3.8.3",
|
||||||
"typescript-json-schema": "^0.42.0",
|
"typescript-json-schema": "^0.42.0",
|
||||||
"xmlhttprequest": "^1.8.0"
|
"xmlhttprequest": "^1.8.0"
|
||||||
|
|
Загрузка…
Ссылка в новой задаче