Related
I need to create a Azure policy which enforces frontdoor firewall to allow only certain IP's
Something like below,
https://github.com/Azure/azure-policy/blob/bbfc60104c2c5b7fa6dd5b784b5d4713ddd55218/samples/EventHub/allowed-event-hub-firewall-ip/azurepolicy.json
I have created the below policy but it is not adding the waf custom rule.
Can someone help to find what's wrong with below policy,
"properties": {
"displayName": "akapolicy",
"policyType": "Custom",
"mode": "All",
"metadata": {
},
"parameters": {},
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Network/FrontDoorWebApplicationFirewallPolicies"
},
{
"anyOf": [
{
"field": "tags['application']",
"exists": true
}
]
}
]
},
"then": {
"details": {
"deployment": {
"properties": {
"mode": "incremental",
"template": {
"$schema": "http://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"apiVersion": "2022-05-01",
"properties": {
"customRules": {
"rules": [
{
"action": "Allow",
"enabledState": "Enabled",
"matchConditions": [
{
"matchValue": [
"1.1.1.1"
],
"matchVariable": "RemoteAddr",
"operator": "Contains"
}
],
"name": "akamairule",
"priority": "1",
"rateLimitDurationInMinutes": "1",
"rateLimitThreshold": "50",
"ruleType": "MatchRule"
}
]
}
}
}
]
}
}
},
"roleDefinitionIds": [
"/providers/Microsoft.Authorization/roleDefinitions/4d97b98b-1d4f-4787-a291-c67834d212e7"
],
"type": "Microsoft.Network/frontdoorWebApplicationFirewallPolicies"
},
"effect": "deployIfNotExists"
}
}
},
}
}
I found a guide on how to create a skill for Alexa that made me use Google as a search engine (thus integrating Google Assistant into Alexa). The problem is that Amazon has upgraded to nodejs 16.x, while the guides are stuck on previous versions. How can I solve the problem?
Running a test using Lambda on Amazon AWS, the error it gives me is the following:
{
"errorMessage": "RequestId: ab04002d-67e6-4144-9c1f-94987a0b8e5e Error: Runtime exited with error: exit status 7",
"errorType": "Runtime.ExitError"
}
nNODE_MODULE_VERSION 72. This version of Node.js requires\nNODE_MODULE_VERSION 93. Please try re-compiling or re-installing\nthe module (for instance, using `npm rebuild` or `npm install`).","code":"ERR_DLOPEN_FAILED","stack":["Error: The module '/var/task/node_modules/#suldashi/lame/build/Release/bindings.node'","was compiled against a different Node.js version using","NODE_MODULE_VERSION 72. This version of Node.js requires","NODE_MODULE_VERSION 93.
I think I need to modify the Lambda function code by uploading an updated zip file, but I don't know how or where to get it.
For example, I uploaded this zip file (github: https://github.com/rokmohar/alexa-assistant/releases) to update Node to version 12.x and update Node packages. Is it possible to do a similar thing with nodejs 16.x?
I believe the problem is in this code:
{
"AWSTemplateFormatVersion": "2010-09-09",
"Metadata":{
"License": "Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License"
},
Description: "This AWS CloudFormation Template is provided for users to install the Alexa Google Assistant skill. It is provided under the Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License. This means that you may use this template provided that it is not for commercial use. You may not host instructions that use this CloudFormation template if you receive monetisation from that page, for example embedded adverts",
"Mappings": {
"RegionMap": {
"us-east-1": {
"BUCKET": "alexagoogleassistantskilluseast1"
},
"eu-west-1": {
"BUCKET": "alexagoogleassistantskilleuwest1"
}
}
},
"Conditions": {
"CorrectAWSRegion": {
"Fn::Or": [
{
"Fn::Equals": [
{
"Ref": "AWS::Region"
},
"eu-west-1"
]
},
{
"Fn::Equals": [
{
"Ref": "AWS::Region"
},
"us-east-1"
]
}
]
},
"IncorrectAWSRegion": {
"Fn::Not": [
{
"Condition": "CorrectAWSRegion"
}
]
}
},
"Resources": {
"S3Bucket": {
"Type": "AWS::S3::Bucket",
"Condition": "CorrectAWSRegion",
"Properties": {
}
},
"DynamoDBtable": {
"Type" : "AWS::DynamoDB::Table",
"Condition": "CorrectAWSRegion",
"Properties" : {
"AttributeDefinitions" : [
{
"AttributeName" : "userId",
"AttributeType" : "S"
}
],
"KeySchema" :
[
{
"AttributeName" : "userId",
"KeyType" : "HASH"
}
]
,
"ProvisionedThroughput" : {
"ReadCapacityUnits" : 5,
"WriteCapacityUnits" : 5
},
"TableName": "AlexaAssistantSkillSettings"
}
},
"LambdaFunctionRole": {
"Type": "AWS::IAM::Role",
"Condition": "CorrectAWSRegion",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"lambda.amazonaws.com"
]
},
"Action": [
"sts:AssumeRole"
]
}
]
},
"Path": "/",
"Policies": [
{
"PolicyName": "GoogleAssistantPolicy",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowLogging",
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": [
"*"
]
},
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": [
{
"Fn::Join": [
"",
[
{
"Fn::GetAtt": [
"S3Bucket",
"Arn"
]
},
"*"
]
]
}
]
},
{
"Effect": "Allow",
"Action": "dynamodb:*",
"Resource": [
{
"Fn::Join": [
"",
[
{
"Fn::GetAtt": [
"DynamoDBtable",
"Arn"
]
},
"*"
]
]
}
]
}
]
}
}
]
}
},
"AlexaSkillFunction": {
"Type": "AWS::Lambda::Function",
"Condition": "CorrectAWSRegion",
"Properties": {
"FunctionName": "alexa-assistant-skill-function",
"Handler": "index.handler",
"Role": {
"Fn::GetAtt": [
"LambdaFunctionRole",
"Arn"
]
},
"Description": "Alexa Skill code for the Google Assistant Skill",
"Code": {
"S3Bucket": {
"Fn::FindInMap": [
"RegionMap",
{
"Ref": "AWS::Region"
},
"BUCKET"
]
},
"S3Key": "index_1.2.zip"
},
"Runtime": "nodejs16.x",
"Timeout": "10",
"MemorySize": "1344",
"Environment": {
"Variables": {
"S3_BUCKET": {
"Ref": "S3Bucket"
},
"API_ENDPOINT": "embeddedassistant.googleapis.com"
}
}
}
},
"AlexaSkillFunctionPermissions": {
"Type": "AWS::Lambda::Permission",
"Condition": "CorrectAWSRegion",
"Properties": {
"FunctionName": {
"Ref": "AlexaSkillFunction"
},
"Action": "lambda:InvokeFunction",
"Principal": "alexa-appkit.amazon.com"
}
}
},
"Outputs": {
"FunctionARN": {
"Condition": "CorrectAWSRegion",
"Value": {
"Fn::GetAtt": [
"AlexaSkillFunction",
"Arn"
]
},
"Description": "Lambda function ARN to be placed in the Amazon Developer Portal"
},
"FunctionError": {
"Condition": "IncorrectAWSRegion",
"Value": "Incorrect AWS Region!!! Must be US-East(N. VIRGINIA) or EU(Ireland)",
"Description": "You must Select US-EAST (North Virgina) if you are located in North America or EU (Ireland) if you are located elsewhere"
}
}
}
Thanks for the help.
I am the autor of the package above. It was just updated to use NodeJs 18.x and latest ASK SKD v2. Can you try to setup with the latest version (currently 1.5.0) and let me know if it works for you.
I'm creating an ARM template that has rules for FTP traffic. I'd like to use the copy command within the probes property of the load balancer to create probes for a range of ports, but I also have other probes that do not need to be repeated (fall outside of the copy). When I try to add both, the ARM template says it's invalid because the probes property is already present. Is it possible to use the "copy" syntax in addition to other value or must the "copy" be the only ARM syntax that builds the entire list of array values?
{
"type": "Microsoft.Network/loadBalancers",
"sku": {
"name": "Standard",
"tier": "Regional"
},
"name": "[variables('lb-csl-private.name')]",
"apiVersion": "2018-10-01",
"location": "[resourceGroup().location]",
"scale": null,
"properties": {
"frontendIPConfigurations": [
{
"name": "LoadBalancerFrontEnd",
"properties": {
"privateIPAddress": "[variables('ip-lb-csl-private')]",
"privateIPAllocationMethod": "Dynamic",
"subnet": {
"id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('vnet-csl.name'), variables('vnet-csl.subnets.loadBalancerName'))]"
}
}
}
],
"copy": [
{
"name": "probes",
"count": 10,
"input": {
"name": "[concat('probe-CSL-PASV-', copyIndex('probes'))]",
"properties": {
"protocol": "Tcp",
"port": "[copyIndex('probes')]",
"inervalInSeconds": 5,
"numberOfProbes": 2
}
}
}
],
"probes": [
{
"name": "probe-CSL-FTP",
"properties": {
"protocol": "Tcp",
"port": 21,
"intervalInSeconds": 5,
"numberOfProbes": 2
}
}
],
"inboundNatRules": [],
"outboundRules": [],
"inboundNatPools": []
}
}
it is possible to do that using variables:
"variables": {
"copy": [
{
"name": "probes",
"count": 10,
"input": {
"name": "[concat('probe-CSL-PASV-', copyIndex('probes'))]",
"properties": {
"protocol": "Tcp",
"port": "[copyIndex('probes')]",
"inervalInSeconds": 5,
"numberOfProbes": 2
}
}
}
],
"otherProbes": [
{
probe1
},
{
probe2
},
etc
]
}
and then, in your load balancer:
"probes": "[concat(variables('probes'), variables('otherProbes'))]"
I have an ARM template where I set up a load balancer and I want to add a number of port openings by adding rules and probes to the LB.
This is the template I have so far:
{
"type": "Microsoft.Network/loadBalancers",
"name": "LB-front",
"apiVersion": "2016-03-30",
"location": "westeurope",
"tags": { },
"properties": {
"frontendIPConfigurations": [
{
"name": "LoadBalancerIPConfig",
"properties": {
"privateIPAllocationMethod": "Dynamic",
"publicIPAddress": {
"id": "[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIPAddresses_lbipdev_0_name'))]"
}
}
}
],
"backendAddressPools": [
{
"name": "LoadBalancerBEAddressPool"
}
],
"loadBalancingRules": [
{
"name": "AppPortLBRule1",
"properties": {
"frontendIPConfiguration": {
"id": "[parameters('loadBalancers_LB_dev_id_6')]"
},
"frontendPort": 80,
"backendPort": 80,
"enableFloatingIP": false,
"idleTimeoutInMinutes": 5,
"protocol": "Tcp",
"loadDistribution": "Default",
"backendAddressPool": {
"id": "[parameters('loadBalancers_LB_dev_id_7')]"
},
"probe": {
"id": "[parameters('loadBalancers_LB_dev_id_8')]"
}
}
},
{
"name": "AppPortLBRule2",
"properties": {
"frontendIPConfiguration": {
"id": "[parameters('loadBalancers_LB_dev_id_9')]"
},
"frontendPort": 81,
"backendPort": 81,
"enableFloatingIP": false,
"idleTimeoutInMinutes": 5,
"protocol": "Tcp",
"loadDistribution": "Default",
"backendAddressPool": {
"id": "[parameters('loadBalancers_LB_dev_id_10')]"
},
"probe": {
"id": "[parameters('loadBalancers_LB_dev_id_11')]"
}
}
},
{
"name": "AppPortLBRule3",
"properties": {
"frontendIPConfiguration": {
"id": "[parameters('loadBalancers_LB_dev_id_12')]"
},
"frontendPort": 82,
"backendPort": 82,
"enableFloatingIP": false,
"idleTimeoutInMinutes": 5,
"protocol": "Tcp",
"loadDistribution": "Default",
"backendAddressPool": {
"id": "[parameters('loadBalancers_LB_dev_id_13')]"
},
"probe": {
"id": "[parameters('loadBalancers_LB_dev_id_14')]"
}
}
}
],
"probes": [
{
"name": "AppPortProbe1",
"properties": {
"protocol": "Tcp",
"port": 80,
"intervalInSeconds": 5,
"numberOfProbes": 2
}
},
{
"name": "AppPortProbe2",
"properties": {
"protocol": "Tcp",
"port": 81,
"intervalInSeconds": 5,
"numberOfProbes": 2
}
},
{
"name": "AppPortProbe3",
"properties": {
"protocol": "Tcp",
"port": 82,
"intervalInSeconds": 5,
"numberOfProbes": 2
}
}
],
"inboundNatRules": [],
"outboundNatRules": [],
"inboundNatPools": []
},
"resources": [],
"dependsOn": [
"[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIPAddresses_lbipdev_1_name'))]"
]
},
(some details omitted)
What I would like to do is to have an array of the port numbers I want to create rules and probes for and loop over those instead of explicitly having to write each rule and probe as a property for the resource.
Basically I would like a parameter or variable in my template like this:
"ports": [ 80, 81, 82, ...]
and that I could loop over this similar to this: https://learn.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-multiple.
Indeed you can! Copy does work with properties!
Create a parameter or variable like this (this example will use parameter array):
"lbRules": {
"type": "array",
"defaultValue": [
{
"name": "httpPort",
"frontendPort": "80",
"backendPort": "80",
"protocol": "tcp"
},
{
"name": "customAppPort",
"frontendPort": "8080",
"backendPort": "8888",
"protocol": "tcp"
},
{
"name": "httpsPort",
"frontendPort": "443",
"backendPort": "443",
"protocol": "tcp"
}
]
}
Use this parameter in the Loadbalancer resource using copy like this that will create that many probes and rules that you defined in your parameter array:
{
"apiVersion": "[variables('lbApiVersion')]",
"type": "Microsoft.Network/loadBalancers",
"name": "[parameters('myLoadBalancer')]",
"location": "[parameters('computeLocation')]",
"dependsOn": [
"[concat('Microsoft.Network/publicIPAddresses/',concat(parameters('lbIPName'),'-','0'))]"
],
"properties": {
"frontendIPConfigurations": [
{
"name": "LoadBalancerIPConfig",
"properties": {
"publicIPAddress": {
"id": "[resourceId('Microsoft.Network/publicIPAddresses',concat(parameters('lbIPName'),'-','0'))]"
}
}
}
],
"backendAddressPools": [
{
"name": "LoadBalancerBEAddressPool",
"properties": {}
}
],
"copy": [
{
"name": "probes",
"count": "[length(parameters('lbRules'))]",
"input": {
"name": "[concat(parameters('lbRules')[copyIndex('probes')].name,'Probe')]",
"properties": {
"intervalInSeconds": 5,
"numberOfProbes": 2,
"port": "[parameters('lbRules')[copyIndex('probes')].backendPort]",
"protocol": "[parameters('lbRules')[copyIndex('probes')].protocol]"
}
}
},
{
"name": "loadBalancingRules",
"count": "[length(parameters('lbRules'))]",
"input": {
"name": "[parameters('lbRules')[copyIndex('loadBalancingRules')].name]",
"properties": {
"frontendIPConfiguration": {
"id": "[concat(resourceId('Microsoft.Network/loadBalancers', parameters('myLoadBalancer')),'/frontendIPConfigurations/LoadBalancerIPConfig')]"
},
"frontendport": "[parameters('lbRules')[copyIndex('loadBalancingRules')].frontendport]",
"backendport": "[parameters('lbRules')[copyIndex('loadBalancingRules')].backendport]",
"enableFloatingIP": false,
"idleTimeoutInMinutes": "5",
"protocol": "[parameters('lbRules')[copyIndex('loadBalancingRules')].protocol]",
"backendAddressPool": {
"id": "[concat(resourceId('Microsoft.Network/loadBalancers', parameters('myLoadBalancer')),'/backendAddressPools/LoadBalancerBEAddressPool')]"
},
"probe": {
"id": "[concat(variables('lbID0'),'/probes/', parameters('lbRules')[copyIndex('loadBalancingRules')].name,'Probe')]"
}
}
}
}
],
"inboundNatPools": []
},
}
}
More info can be found here:
https://learn.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-multiple#property-iteration
https://learn.microsoft.com/en-us/azure/azure-resource-manager/templates/copy-properties
You can only apply the copy object to a top-level resource.
You cannot apply it to a property on a resource type, or to a child resource.
"resources": [
{
"type": "{provider-namespace-and-type}",
"name": "parentResource",
"copy": {
/* yes, copy can be applied here */
},
"properties": {
"exampleProperty": {
/* no, copy cannot be applied here */
}
},
"resources": [
{
"type": "{provider-type}",
"name": "childResource",
/* copy can be applied if resource is promoted to top level */
}
]
}
]
Source of Quotation: Deploy multiple instances of resources in Azure Resource Manager templates
You can loop over properties in ARM Template ONLY IF the copy object is applied to a top-level resource, which is in your case the "Microsoft.Network/loadBalancers", but that will also create multiple copy of the said resource.
If this is not what you want to achieve, I would recommend you to keep your existing way until ARM Template support copy object to property on a resource type in the future.
It is now possible to loop on properties or on child resources as stated in https://learn.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-multiple#property-iteration or in
https://learn.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-multiple#create-multiple-instances-of-a-child-resource
You can a child resource extension (e.g. WebSite/Extension) as a top-level resource by following the format for the type:
{resource-provider-namespace}/{parent-resource-type}/{child-resource-type}.
For instance
Microsoft.Web/sites/siteextensions
You have also to reference the parent resource in the child resource by a concat. For instance:
"name": "[concat('mywebsite', '/', 'myextension', copyIndex())]"
What you want to achieve is possible with the take function.
You linked the proper documentation site yourself. Go to the link you posted and check out the section "Create multiple instances when copy won't work".
in your case this would look like this:
"variables": {
"probeArray": [
{
"name": "AppPortProbe1",
"properties": {
"protocol": "Tcp",
"port": 80,
"intervalInSeconds": 5,
"numberOfProbes": 2
}
},
{
"name": "AppPortProbe2",
"properties": {
"protocol": "Tcp",
"port": 81,
"intervalInSeconds": 5,
"numberOfProbes": 2
}
},
{
"name": "AppPortProbe3",
"properties": {
"protocol": "Tcp",
"port": 82,
"intervalInSeconds": 5,
"numberOfProbes": 2
}
}
],
You then create an parameter specifying how many probes you want
"parameters": {
...
"numProbes": {
"type": "int",
"maxValue": 3,
"metadata": {
"description": "This parameter allows you to select the number of probes you want"
}
}
Finally you use take inside the resource:
"resources": [
...
{
"type": "Microsoft.Network/loadBalancers",
"properties": {
...
"probes": "[take(variables('probeArray'),parameters('numProbes'))]"
},
...
}
...
}
]
If you continue the through the documentation you will see that you can get even more crazy and combine copy and take with linked templates.
I am trying to modify an ARM template that I have which deploys some VMs and defines some autoscale rules (you can see the full template at https://gist.github.com/jinky32/d80e0ab2137236ff262484193f93c946, it is based on the template at https://github.com/gbowerman/azure-myriad/tree/master/vmss-ubuntu-scale).
I am trying to add in some load balancer rules so that traffic is spread across the new VMs as they are generated in reponse to the autoscale rules that are defined.
When I run this template via Azure CLI I get no errors in terminal but the deployment fails. Digging into the error events I see two:
statusCode:BadRequest serviceRequestId:ef42ec66-600e-4fb9-b4e2-dc2c06dda79c statusMessage:{"error":{"code":"InvalidRequestFormat","message":"Cannot parse the request.","details":[{"code":"InvalidJsonReferenceFormat","message":"Reference Id cc2bepool is not formatted correctly. The Id is expected to reference resources of type loadBalancers/backendAddressPools. Path properties.loadBalancingRules[0].properties.backendAddressPool."}]}} responseBody:{"error":{"code":"InvalidRequestFormat","message":"Cannot parse the request.","details":[{"code":"InvalidJsonReferenceFormat","message":"Reference Id cc2bepool is not formatted correctly. The Id is expected to reference resources of type loadBalancers/backendAddressPools. Path properties.loadBalancingRules[0].properties.backendAddressPool."}]}}
and
statusCode:BadRequest statusMessage:{"error":{"code":"InvalidRequestFormat","message":"Cannot parse the request.","details":[{"code":"InvalidJsonReferenceFormat","message":"Reference Id cc2bepool is not formatted correctly. The Id is expected to reference resources of type loadBalancers/backendAddressPools. Path properties.loadBalancingRules[0].properties.backendAddressPool."}]}}
I've put some of the relevant variables below and have also included my loadbalancer object but I believe that the issue is related to how I am referencing backendAddressPool:
"loadBalancingRules": [
{
"name": "LBRule",
"properties": {
"frontendIPConfiguration": {
"id": "[variables('frontEndIPConfigID')]"
},
"backendAddressPool": {
"id": "[variables('bePoolName')]"
},
but I'm confused because I refer to it the same way elsewhere. Any advice on how to do this correctly much appreciated.
"variables": {
....
"loadBalancerName": "[concat(parameters('vmssName'), 'lb')]",
"lbProbeID": "[concat(variables('lbID'),'/probes/tcpProbe')]",
"publicIPAddressID": "[resourceId('Microsoft.Network/publicIPAddresses',variables('publicIPAddressName'))]",
"lbID": "[resourceId('Microsoft.Network/loadBalancers',variables('loadBalancerName'))]",
"natPoolName": "[concat(parameters('vmssName'), 'natpool')]",
"bePoolName": "[concat(parameters('vmssName'), 'bepool')]",
....
....
}
.....
.....
{
"type": "Microsoft.Network/loadBalancers",
"name": "[variables('loadBalancerName')]",
"location": "[variables('location')]",
"apiVersion": "[variables('networkApiVersion')]",
"dependsOn": [
"[concat('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]"
],
"properties": {
"frontendIPConfigurations": [
....
],
"backendAddressPools": [
{
"name": "[variables('bePoolName')]"
}
],
"inboundNatPools": [
{
"name": "[variables('natPoolName')]",
...
},
{
"name": "natpooltileserver",
....
},
{
"name": "natpool2",
....
],
"loadBalancingRules": [
{
"name": "LBRule",
"properties": {
"frontendIPConfiguration": {
"id": "[variables('frontEndIPConfigID')]"
},
"backendAddressPool": {
"id": "[variables('bePoolName')]"
},
"protocol": "tcp",
"frontendPort": 80,
"backendPort": 80,
"enableFloatingIP": false,
"idleTimeoutInMinutes": 5,
"probe": {
"id": "[variables('lbProbeID')]"
}
}
}
],
"probes": [
{
"name": "tcpProbe",
"properties": {
"protocol": "tcp",
"port": 80,
"intervalInSeconds": 5,
"numberOfProbes": 2
}
}
]
}
},
please go to the portal and open a support request to see what's wrong with your template edits.