I have an ARM template for deploying a Service Fabric cluster in Azure pipeline:
- task: AzureResourceManagerTemplateDeployment@3
displayName: 'Deploy SF cluster'
inputs:
deploymentScope: 'Resource Group'
subscriptionId: '${{ parameters.SubscriptionId }}'
azureResourceManagerConnection: '${{ parameters.ArmConnection }}'
action: 'Create Or Update Resource Group'
resourceGroupName: '${{ parameters.ResourceGroupName }}'
location: 'West Europe'
templateLocation: 'Linked artifact'
csmFile: '$(Build.SourcesDirectory)/pipelines/templates/sfcluster.json'
csmParametersFile: '$(Build.SourcesDirectory)/pipelines/templates/sfcluster-params.json'
overrideParameters: '-certificateThumbprint $(Thumbprint) -sourceVaultResourceId $(KeyvaultId) -certificateUrlValue $(SecretId)'
deploymentMode: 'Incremental'
The ARM template works well (since many days and in 5 different pipelines) when I use:
"osProfile": {
"adminUsername": "RdpUsername",
"adminPassword": "RdpPassword",
"computernamePrefix": "[variables('vmNodeType0Name')]",
"secrets": [
{
"sourceVault": {
"id": "[parameters('sourceVaultResourceId')]"
},
"vaultCertificates": [
{
"certificateStore": "My",
"certificateUrl": "[parameters('certificateUrlValue')]"
}
]
}
]
},
Having hardcoded RDP credentials is however a security issue, so I would like to Use Azure Key Vault to pass secure parameter value during deployment
So I add 2 random secret strings to the Keyvault, which is deployed earlier in the pipeline and then try:
"osProfile": {
"adminUsername": {
"reference": {
"keyVault": {
"id": "[parameters('sourceVaultResourceId')]"
},
"secretName": "RdpUsername"
}
},
"adminPassword": {
"reference": {
"keyVault": {
"id": "[parameters('sourceVaultResourceId')]"
},
"secretName": "RdpPassword"
}
},
"computernamePrefix": "[variables('vmNodeType0Name')]",
"secrets": [
{
"sourceVault": {
"id": "[parameters('sourceVaultResourceId')]"
},
"vaultCertificates": [
{
"certificateStore": "My",
"certificateUrl": "[parameters('certificateUrlValue')]"
}
]
}
]
},
Unfortunately this produces the error:
Unexpected character encountered while parsing value: {. Path 'properties.virtualMachineProfile.osProfile.adminUsername', line 1, position 3178.
My question is: why is the bracket {
unexpected there?
My ARM template is based on the azure-quickstart-templates/service-fabric-secure-cluster-5-node-1-nodetype and as written above works with the hardcoded values.
UPDATE:
Here is my sfcluster-params.json (but also please note the overrideParameters
in the pipeline task listed below and being filled with pipeline variables set by Keyvault deployment):
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"clusterName": {
"value": "sfcluster"
}
}
}
And here a bigger part of my Azure pipeline:
# deploy KeyVault by ARM template and output VinHashKey and SF Cluster certificate thumbsprint
- task: AzureResourceManagerTemplateDeployment@3
displayName: 'Deploy Keyvault'
inputs:
deploymentScope: 'Resource Group'
subscriptionId: '${{ parameters.SubscriptionId }}'
azureResourceManagerConnection: '${{ parameters.ArmConnection }}'
action: 'Create Or Update Resource Group'
resourceGroupName: '${{ parameters.ResourceGroupName }}'
location: 'West Europe'
templateLocation: 'Linked artifact'
csmFile: '$(Build.SourcesDirectory)/pipelines/templates/keyvault.json'
csmParametersFile: '$(Build.SourcesDirectory)/pipelines/templates/keyvault-params.json'
deploymentMode: 'Incremental'
# collect outputs from the above ARM task and put them into pipeline vars
- task: ARM Outputs@5
displayName: 'Collect Keyvault output'
inputs:
ConnectedServiceNameSelector: 'ConnectedServiceNameARM'
ConnectedServiceNameARM: '${{ parameters.ArmConnection }}'
resourceGroupName: '${{ parameters.ResourceGroupName }}'
whenLastDeploymentIsFailed: 'fail'
# import the certificate my-self-signed-cert into the Keyvault if it is missing there
- task: AzurePowerShell@5
displayName: 'Import certificate'
inputs:
azureSubscription: '${{ parameters.ArmConnection }}'
ScriptType: 'InlineScript'
azurePowerShellVersion: '3.1.0'
Inline: |
$Cert = Get-AzKeyVaultCertificate -VaultName $(KeyVaultName) -Name my-self-signed-cert
if (!$Cert) {
$Pwd = ConvertTo-SecureString -String MyPassword -Force -AsPlainText
$Base64 = 'MII....gfQ'
$Cert = Import-AzKeyVaultCertificate -VaultName $(KeyVaultName) -Name my-self-signed-cert -CertificateString $Base64 -Password $Pwd
}
# set the pipeline variables Thumbprint and SecretId - needed for SF deployment
echo "##vso[task.setvariable variable=Thumbprint]$($Cert.Thumbprint)"
echo "##vso[task.setvariable variable=SecretId]$($Cert.SecretId)"
# deploy SF cluster by ARM template and use the SF certificate thumbsprint as admin cert
- task: AzureResourceManagerTemplateDeployment@3
displayName: 'Deploy SF cluster'
inputs:
deploymentScope: 'Resource Group'
subscriptionId: '${{ parameters.SubscriptionId }}'
azureResourceManagerConnection: '${{ parameters.ArmConnection }}'
action: 'Create Or Update Resource Group'
resourceGroupName: '${{ parameters.ResourceGroupName }}'
location: 'West Europe'
templateLocation: 'Linked artifact'
csmFile: '$(Build.SourcesDirectory)/pipelines/templates/sfcluster.json'
csmParametersFile: '$(Build.SourcesDirectory)/pipelines/templates/sfcluster-params.json'
overrideParameters: '-certificateThumbprint $(Thumbprint) -sourceVaultResourceId $(KeyvaultId) -certificateUrlValue $(SecretId)'
deploymentMode: 'Incremental'
Finally, here the sfcluster.json - it is too big to put at Stackoverflow.
A keyVault reference can only be used as a parameter value - so in a param file or the parameters property of a deployment. You can't use it directly as a property value on a resource.