Authorized IP Addresses for AKS using ARM Template - azure

I am trying to deploy an AKS with authorized IP ranges enabled by default. I'm utilizing the following in my code:
parameters: {
"AuthorizedIpRanges": {
"type": "string",
"default": "1.0.0.1,1.0.0.2,1.0.0.3"
}
}
variables: {
"authorizedIpRanges": "[split(parameters('AuthorizedIPRanges'),',')]"
}
properties: {
"apiServerAccessProfile": {
"authorizedIPRanges": "[variables('authorizedIpRanges')]"
}
}
This deploys successfully, and I can see the Authorized IP Ranges checkbox checked in Portal, but there are no IP addresses listed.
I'm aware it takes an array of strings, but when I try to set the AuthorizedIpRanges type to "array" it is unable to process the json at all. Trying without the split gives "APIServerAccessProfile.properties.apiServerAccessProfile.authorizedIPRanges accept type []string, not type string"
I also do not have any spaces after the commas, as shown in the example above.
Any help is appreciated!

Related

Deploying ARM Template for an API Connection that uses OnPrem Data Gateway succeeds but the authType and gateway parameters are missing

I've been banging my head against a brick wall on this.
I'm trying to deploy via Azure DevOps pipeline, a bicep/ARM Template an API Connection that uses a Custom Connector that is linked to an On-prem API via a Data Gateway.
Here is my bicep file...
param connectionName string
param displayName string
param gatewayResourceGroup string
param gatewayName string
param connectorName string
param location string = resourceGroup().location
resource connector 'Microsoft.Web/customApis#2016-06-01' existing = {
name: connectorName
}
resource gatewayApi 'Microsoft.Web/connectionGateways#2016-06-01' existing = {
name: gatewayName
scope: resourceGroup(gatewayResourceGroup)
}
resource apiConnection 'Microsoft.Web/connections#2016-06-01' = {
name: connectionName
location: location
properties: {
displayName: displayName
nonSecretParameterValues: {
authType: 'anonymous'
#disable-next-line BCP036
gateway: {
name: gatewayName
id: gatewayApi.id
type: 'Microsoft.Web/connectionGateways'
}
}
api: {
name: connector.name
displayName: 'CONNECTOR ${connectorName}'
id: connector.id
type: 'Microsoft.Web/customApis'
}
}
}
I issue is the nonSecretParameterValues.
They don't go anywhere.
The API Connection is deployed like...
What makes this a little worse is the deployment is successful...
But if I drill into the Operation details I can see there were two issues...
"overallStatus": "Error",
"statuses": [
{
"status": "Error",
"target": "authType",
"error": {
"code": "ConfigurationNeeded",
"message": "Parameter value missing."
}
},
{
"status": "Error",
"target": "gateway",
"error": {
"code": "ConfigurationNeeded",
"message": "Parameter value missing."
}
}
],
Very frustrating.
Now I can manually add the values I intended to be there for the authType and gateway parameters after the deployment is "successful". Then my logic app that uses this API Connection and Custom Connector to Onprem Gateway works as expected.
But the exported template for the API Connection does not change between the connection having missing parameters (in the UI) or after I manually enter the values.
I have also tried added some Powershell after the deployment to pick up the connection and to try settings the "missing" values and updating the resource from there.
I can see another API Connection via Powershell which is correctly set with the authType and gateway parameters.
But when I try, to set these on the resource I need to "fix" it also complains...
I would really like to have the API Connection deployment fully via Azure DevOps pipeline.
NOTE: I find it very odd to have to use the #disable-next-line BCP036 to disable the warning in VSCode. And even opening the built ARM Template will give a warning on the "gateway" property name. I even tried replacing the "object" with just the resource id and that didn't help.
The parameters should be in a parameterValues property object:
resource apiConnection 'Microsoft.Web/connections#2016-06-01' = {
name: connectionName
location: location
properties: {
displayName: displayName
parameterValues: {
authType: 'anonymous'
gateway: {
id: gatewayApi.id
}
}
...
}
}
Suggestion:
The nonSecretParameterValues object must be in the format of a dictionary. I cannot find any hard documentation about this as a data structure, but it's mentioned several times.
nonSecretParameterValues: {
authType: 'anonymous'
gateway-name: gatewayName
gateway-id: gatewayApi.id
gateway-type: 'Microsoft.Web/connectionGateways'
}
Hope this helps.

Convert ARM template parameter of type Array to use in Powershell of type String[]

Objective here is to create an inbound rule in windows firewall, to add multiple remote addresses taken from the template parameter, using a single powershell command.
I have a parameter vnAddressPrefixes of type Array which contains Address Prefixes (as given in below default value).
"parameters": {
// ... Some more fields not relevant to this question
"vnAddressPrefixes": {
"defaultValue": [ "10.0.0.0/16", "10.0.0.0/24" ],
"type": "Array"
}
}
I have a custom script extension (as given below) which runs a powershell command to create an inbound rule in windows firewall, to add multiple remote addresses.
"resources": [
{
// ... Some more fields not relevant to this question
"type": "Microsoft.Compute/virtualMachines/extensions",
"properties": {
// ... Some more fields not relevant to this question
"publisher": "Microsoft.Compute",
"type": "CustomScriptExtension",
"protectedSettings": {
"commandToExecute": "[variables('commandToExecuteInVm')]"
}
}
}
]
The variable commandToExecuteInVm is constructed from the parameter vnAddressPrefixes as given below.
(I am trying to convert the array value from [10.0.0.0/16,10.0.0.0/24] to #("10.0.0.0/16","10.0.0.0/24")
"variables": {
// Variable for converting array to powershell format. Eg.: [10.0.0.0/16,10.0.0.0/24] to #("10.0.0.0/16","10.0.0.0/24")
"addressPrefixesTemp1": "[string(parameters('vnAddressPrefixes'))]", // Convert to string
"addressPrefixesTemp2": "[replace(variables('addressPrefixesTemp1'), '[', '#(\"')]", // Convert [ to #("
"addressPrefixesTemp3": "[replace(variables('addressPrefixesTemp2'), ',', '\", \"')]", // Convert , to ", "
"addressPrefixesTemp4": "[replace(variables('addressPrefixesTemp3'), ']', '\")')]", // Convert ] to ")
// Variable for adding an inbound rule in windows firewall, for specific port, for accessing using application gateway fqdn
"addFirewallInboundRuleAllow8088": "[concat('New-NetFirewallRule -DisplayName Allow_Port_8088 -Direction Inbound -LocalPort 8088 -Protocol TCP -Action Allow -RemoteAddress ', variables('addressPrefixesTemp4'), ' ; ')]",
// Variable to store the final command to be executed in the VM
"commandToExecuteInVm": "[concat('powershell -ExecutionPolicy Unrestricted ', variables('addFirewallInboundRuleAllow8088'))]"
}
I am getting the below error which mentions that the value provided for RemoteAddress is invalid.
Command execution finished, but failed because it returned a non-zero
exit code of: '1'. The command had an error output of:
'New-NetFirewallRule : The address is invalid. Addresses may be
specified as IP addresses, ranges, or subnets. Also, the following
address keywords are allowed in certain places: LocalSubnet, DNS,
DHCP, WINS, DefaultGateway, Internet, Intranet, Intran...' For more
information, check the instance view by executing Get-AzVmssVm or
Get-AzVm (https://aka.ms/GetAzVm). These commands can be executed
using CloudShell (https://aka.ms/CloudShell)
Looks like powershell expects the double quotes to be escaped.
So, the array value should be converted from [10.0.0.0/16,10.0.0.0/24] to #(\"10.0.0.0/16\",\"10.0.0.0/24\"). (Notice that the double quotes is escaped).
Which means, a backslash (which should also be escaped) had to be added before the escaped double quote.
So, \" will become \\\".
"variables": {
// Variable for converting array to powershell format. Eg.: [10.0.0.0/16,10.0.0.0/24] to #(\"10.0.0.0/16\",\"10.0.0.0/24\")
"addressPrefixesTemp1": "[string(parameters('vnAddressPrefixes'))]", // Convert to string
"addressPrefixesTemp2": "[replace(variables('addressPrefixesTemp1'), '[', '#(\\\"')]", // Convert [ to #(\"
"addressPrefixesTemp3": "[replace(variables('addressPrefixesTemp2'), ',', '\\\", \\\"')]", // Convert , to \", \"
"addressPrefixesTemp4": "[replace(variables('addressPrefixesTemp3'), ']', '\\\")')]", // Convert ] to \")
}
Let me know if there is any other better way of converting ARM template parameter of type Array to use in Powershell command of type String[], without having to use these many string manipulations.

Azure CORS Variable Allowed Origins

Whenever a new release pipeline is ran in Azure DevOps, the URL Is changed.. currently my ARM template has a hard-coded URL which can be annoying to keep on adding in manually.
"cors": {
"allowedOrigins": [
"[concat('https://',parameters('storage_account_name'),'.z10.web.core.windows.net')]"
}
The only thing that changes is the 10 part in the z10 so essentially i want it to be something like
[concat('https://',parameters('storage_account_name'),'.z', '*', '.web.core.windows.net')] I dont know if something like that is valid but essentially its so that the cors policy will accept the URL regardless of the z number.
Basically speaking this is not possible, because of the CORS standard (see docs).
which allows only for exact origins, wildcard, or null.
For instance, ARM for Azure Storage is also following this pattern allowing you to put a list of exact origins or a wildcard (see ARM docs)
However, if you know your website name, in your ARM you can receive the full host and use it in your CORS:
"[reference(resourceId('Microsoft.Web/sites', parameters('SiteName')), '2018-02-01').defaultHostName]"
The same with a static website (which is your case I guess) if you know the storage account name:
"[reference(concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName')), '2019-06-01', 'Full').properties.primaryEndpoints.web]"
Advance reference output manipulation
Answering on comment - if you would like to replace some characters in the output from the reference function the easiest way is to use build-in replace function (see docs)
In case you need a more advanced scenario I am pasting my solution by introducing a custom function which is removing https:// and / from the end so https://contonso.com/ is transformed to contonso.com:
"functions": [
{
"namespace": "lmc",
"members": {
"replaceUri": {
"parameters": [
{
"name": "uriString",
"type": "string"
}
],
"output": {
"type": "string",
"value": "[replace(replace(parameters('uriString'), 'https://',''), '/','')]"
}
}
}
}
],
# ...(some code)...
"resources": [
# ... (some resource)...:
"properties": {
"hostName": "[lmc.replaceUri(reference(variables('storageNameCdn')).primaryEndpoints.blob)]"
}
]

Azure LogicApp ARM template and AzSK checker

I am working on ARM template development for LogicApp and want to make my ARM template complaint to AzSk.
In my template I have following required objects for this component:
"ipAddressRangeForContents": {
"type": "array",
"defaultValue": [],
"metadata": {
"description": "(AzSk required this parameter to be set) IPv4 or IPv6 address range, this will restrict content IP range. This array should have object as a member with following key 'addressRange'. You can specify as many subnets as you want"
}
},
"ipAddressRangeForInbound": {
"type": "array",
"defaultValue": [],
"metadata": {
"description": "(AzSk required this parameter to be set) IPv4 or IPv6 address range, this will restrict inbound IP range. This array should have object as a member with following key 'addressRange'. You can specify as many subnets as you want. Default value is empty array which will restric access to 'Only other Logic Apps'."
}
Here is an example from parameters file for same section:
"ipAddressRangeForContents": {
"value": [
{
"addressRange": "10.123.0.0/24"
},
{
"addressRange": "10.124.0.0/24"
}
]
},
"ipAddressRangeForInbound": {
"value": [
{
"addressRange": "10.135.0.0/24"
},
{
"addressRange": "10.136.0.0/24"
}
]
}
The reason I implemented it this way is flexibility for user to specify as many address ranges as user wants.
AzSk returning me an error if I scan my ARM template:
Starting analysis: [FileName: .\logicapp.json]
--------------------------------------------------------------------------------
Failed: [Azure_LogicApps_AuthZ_Provide_Triggers_Access_Control]
Failed: [Azure_LogicApps_AuthZ_Provide_Contents_Access_Control]
--------------------------------------------------------------------------------
Summary Total Failed
------- ----- ------
High 2 2
------ ------ ------
Total 2 2
------ ------ ------
Even if my template has these parameters.
The reason it's failing it cannot locate property addressRange inside ARM template:
ExpectedProperty
$.properties.accessControl.triggers.allowedCallerIpAddresses.addressRange
$.properties.accessControl.contents.allowedCallerIpAddresses.addressRange
I can fix it by hardcoding my template to:
"properties": {
"accessControl": {
"contents": {
"allowedCallerIpAddresses": {
"addressRange": "[variables('some_range')]"
}
But this will make it less functional since it can accept only one addressRange at deployment phase.
Is there is a way to make template complaint and flexible in the same time?
Thank you in advance!

Unable to use Resource Functions for Azure Resource Manager Templates

My parameters file looks as follows:
{
"$schema":"http://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion":"1.0.0.0",
"parameters":{
"siteName":{
"value":"my-api-application"
},
"appServicePlanName":{
"value":"MyServicePlan"
},
"siteLocation":{
"value":"West US"
},
"vaultResourceGroup": {
"value":"my-vault-res-group"
},
"vaultName": {
"value":"my-keyvault"
},
"nodeEnv": {
"value":"development"
},
"adminPassword": {
"reference": {
"keyVault": {
"id": "/subscriptions/yyyyyyyy-xxxx-xxxx-xxxx-yyyyyyyy/resourceGroups/my-vault-res-group/providers/Microsoft.KeyVault/vaults/my-keyvault"
},
"secretName": "adminPassword"
}
}
}
}
The adminPassword value will be picked up from the specified KeyVault, with the particular id. However, I have to hard code the "id" value.
According to this link, I could specify the id using some thing like this:
resourceId(subscription().subscriptionId, parameters('vaultResourceGroup'), 'Microsoft.KeyVault/vaults', parameters('vaultName'))]
However, when using the above syntax/Resource Functions, I receive an error while releasing and deploying my App Service using the VSTS (I used Azure Resource Group Deployment task for APP deployment). The error is some what like this:
The id must be of the following format:
/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}
Not sure what am I doing wrong?
You're not doing anything wrong, that's intentional. You must use a literal resourceId in the parameters file (parameters files don't allow for function use).
If you have a scenario for a dynamic KeyVault id you can use a nested deployment:
https://learn.microsoft.com/en-us/azure/azure-resource-manager/resource-manager-keyvault-parameter#reference-a-secret-with-dynamic-id

Resources