02-Jul-2020
04:59
- last edited on
22-Nov-2022
15:13
by
JimmyPackets
Having some trouble getting rules added to an LTM policy using iControl REST API and PowerShell. Currently I am able to get the policy into Draft status, and I can add a rule... but I am getting stuck in the formatting for the rule actions and conditions. Does anyone know how these are supposed to be formatted?
The only examples and guidance I have been able to find don't show how to add any actions to the rules.
https://clouddocs.f5.com/api/icontrol-rest/APIRef_tm_ltm_policy.html
rules array_structure optional read/write
https://devcentral.f5.com/s/articles/icontrol-rest-cookbook-ltm-policy-ltm-policy-33300
curl -sku admin:admin https://<host>/mgmt/tm/ltm/policy/~Common~Drafts~<TestPolicy>/rules \
-X POST -H "Content-type:application/json" \
-d '{"name":"<SampleRule>", "description":"sat1" }'
The above example shows how to create a rule and give it a description, but not how to add anything to it. Any help is appreciated.
Code I have used so far for creating the Draft and Rule:
$user = "admin"
$pass = "admin"
$url = "<my f5 url>"
$header = @{"Authorization" = "Basic "+[System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("$user"+":"+"$pass"));}
$policy = "TEST_POLICY_AUTOMATION"
$DraftBody = @{
"createDraft" = $True
}
$RulesBody = @{
"name" = "Test.API"
"description" = "I am a test"
}
### Create a draft from a policy that already exists
Invoke-RestMethod -Uri https://$url/mgmt/tm/ltm/policy/$Policy -Method PATCH -Headers $Header -Body (ConvertTo-Json $DraftBody) -ContentType "application/json"
### Attempts at modifying/adding rules to the policy in draft
### Creating the rule with name Test.API and description "I am a test" works but have been unable to add actions
Invoke-RestMethod -Uri https://$url/mgmt/tm/ltm/policy/~Common~Drafts~$Policy/rules -Method POST -Headers $Header -Body (ConvertTo-Json $RulesBody) -ContentType 'application/json'
02-Jul-2020
08:03
- last edited on
21-Nov-2022
16:21
by
JimmyPackets
Hello,
Far as I know you need to create a rule, then add actions and conditions on it.
e.g.
# Create a policy draft
curl -kv -u admin:admin https://localhost/mgmt/tm/ltm/policy \
-X POST -H "Content-type:application/json" \
-d '{ "name": "/Common/Drafts/policy_vs_devcentral", "strategy": "first-match"}' | jq "."
# Add a rule
curl -kv -u "admin:admin" https://localhost/mgmt/tm/ltm/policy/~Common~Drafts~policy_vs_devcentral/rules \
-X POST -H "Content-type:application/json" \
-d '{"name": "ruleTest" }' | jq "."
# Add conditions and actions to a rule
curl -kv -u "admin:admin" -X PUT https://localhost/mgmt/tm/ltm/policy/~Common~Drafts~policy_vs_devcentral/rules/ruleTest \
-H "Content-type: application/json" \
-d @- << EOF | jq "."
{
"actions": [
{
"name": "0",
"request": true,
"forward": true,
"pool": "/Common/pool_test"
}
],
"conditions": [
{
"name":"0",
"request": true,
"httpHost": true,
"equals": true,
"values": [
"www.mydomain.net"
]
}
]
}
EOF
A tip to easy know all parameters for a certain rule, you create a manually example then retrieve that actions and conditions to understand what parameters you need to fill.
e.g.
I manually created a rule "ruleRedirect" to redirect traffic when host equals "www.test.net" and path equals "/" to a home page:
So, I get conditions and actions from that rule name:
curl -k -u "admin:admin" https://localhost/mgmt/tm/ltm/policy/~Common~Drafts~policy_vs_devcentral/rules/ruleRedirect/conditions |jq "."
{
"kind": "tm:ltm:policy:rules:conditions:conditionscollectionstate",
"selfLink": "https://localhost/mgmt/tm/ltm/policy/~Common~Drafts~policy_vs_devcentral/rules/ruleRedirect/conditions?ver=14.1.2.2",
"items": [
{
"kind": "tm:ltm:policy:rules:conditions:conditionsstate",
"name": "0",
"fullPath": "0",
"generation": 2463,
"selfLink": "https://localhost/mgmt/tm/ltm/policy/~Common~Drafts~policy_vs_devcentral/rules/ruleRedirect/conditions/0?ver=14.1.2.2",
"all": true,
"caseInsensitive": true,
"equals": true,
"external": true,
"httpHost": true,
"index": 0,
"present": true,
"remote": true,
"request": true,
"values": [
"www.test.net"
]
},
{
"kind": "tm:ltm:policy:rules:conditions:conditionsstate",
"name": "1",
"fullPath": "1",
"generation": 2463,
"selfLink": "https://localhost/mgmt/tm/ltm/policy/~Common~Drafts~policy_vs_devcentral/rules/ruleRedirect/conditions/1?ver=14.1.2.2",
"all": true,
"caseInsensitive": true,
"equals": true,
"external": true,
"httpUri": true,
"index": 0,
"present": true,
"remote": true,
"request": true,
"values": [
"/"
]
}
]
}
curl -k -u "admin:admin" https://localhost/mgmt/tm/ltm/policy/~Common~Drafts~policy_vs_devcentral/rules/ruleRedirect/actions |jq "."
{
"kind": "tm:ltm:policy:rules:actions:actionscollectionstate",
"selfLink": "https://localhost/mgmt/tm/ltm/policy/~Common~Drafts~policy_vs_devcentral/rules/ruleRedirect/actions?ver=14.1.2.2",
"items": [
{
"kind": "tm:ltm:policy:rules:actions:actionsstate",
"name": "0",
"fullPath": "0",
"generation": 2463,
"selfLink": "https://localhost/mgmt/tm/ltm/policy/~Common~Drafts~policy_vs_devcentral/rules/ruleRedirect/actions/0?ver=14.1.2.2",
"code": 0,
"expirySecs": 0,
"httpReply": true,
"length": 0,
"location": "https://www.test.net/home",
"offset": 0,
"port": 0,
"redirect": true,
"request": true,
"status": 0,
"timeout": 0,
"vlanId": 0
}
]
}
Now I know that to create a redirection rule this is the json body to push:
{
"conditions": [
{
"name": "0",
"request": true,
"httpHost": true,
"equals": true,
"values": [
"www.test.net"
]
},
{
"name": "1",
"request": true,
"httpUri": true,
"equals": true,
"values": [
"/"
]
} ],
"actions": [
{
"name": "0",
"request": true,
"httpReply": true,
"redirect": true,
"location": "https://www.test.net/home"
} ]
}
I hope this helps.
Regards
02-Jul-2020
08:39
- last edited on
21-Nov-2022
16:21
by
JimmyPackets
This does help a lot... still encountering some issues though... for the Boolean values if I send them as true of false I either get:
Invoke-RestMethod : {"code":400,"message":"Found unexpected json boolean at configuration item /ltm/policy/~Common~Drafts~TEST_POLICY_AUTOMATION/rules/Testing/conditions/equals. The json boolean is
true.","errorStack":[],"apiError":1}
or
Invoke-RestMethod : {"code":400,"message":"Found unexpected json string at configuration item /ltm/policy/~Common~Drafts~TEST_POLICY_AUTOMATION/rules/Testing/conditions/equals. The json string is
\"true\".","errorStack":[],"apiError":1}
This is the JSON I am using in my script, basing it off what you sent as a test
$ActionsBody = [ordered]@{
actions = @{
name = "0"
request = $true
forward = $true
pool = '/Common/pool_test'
}
conditions =@{
name = "0"
request = "true"
httpHost = "true"
equals = "true"
values = "www.mydomain.net"
}
}
Invoke-RestMethod -Uri https://$url/mgmt/tm/ltm/policy/~Common~Drafts~$Policy/rules/Testing -Method PUT -Headers $Header -Body (ConvertTo-Json $ActionsBody) -ContentType 'application/json'
02-Jul-2020 08:51
If I'm not wrong, PS writes True and False as first letter capitalized.
Try converting to a lower case string output and do not surround it with quotes.
This way works for you?
$ActionsBody = [ordered]@{
actions = @{
name = "0"
request = $true
forward = $true
pool = '/Common/pool_test'
}
conditions =@{
name = "0"
request = $true
httpHost = $true
equals = $true
values = "www.mydomain.net"
}
}
$ActionsBody |ConvertTo-Json
Regards
02-Jul-2020
09:00
- last edited on
21-Nov-2022
16:21
by
JimmyPackets
This is what I get now... Everything seems correct...
PS > $jsonBody = $ActionsBody | ConvertTo-Json
PS > $jsonBody
{
"conditions": {
"name": "0",
"request": true,
"httpHost": true,
"equals": true,
"values": "www.mydomain.net"
}
}
PS > Invoke-RestMethod -Uri https://$url/mgmt/tm/ltm/policy/~Common~Drafts~$Policy/rules/Testing -Method PUT -Headers $Header -Body $jsonBody -ContentType 'application/json'
Invoke-RestMethod : {"code":400,"message":"Found unexpected json string at configuration item /ltm/policy/~Common~Drafts~TEST_POLICY_AUTOMATION/rules/Testing/conditions/name. The json string is
02-Jul-2020 09:11
This way looks good for me:
$ActionsBody = [ordered]@{
actions = @{
name = "0"
request = $true
forward = $true
pool = '/Common/pool_test'
}
conditions =@{
name = "0"
request = $true
httpHost = $true
equals = $true
values = "www.mydomain.net"
}
}
Invoke-RestMethod -Uri https://$url/mgmt/tm/ltm/policy/~Common~Drafts~$Policy/rules/Testing -Method PUT -Headers $Header -Body (ConvertTo-Json $ActionsBody) -ContentType 'application/json'
02-Jul-2020 09:08
Alright... got it working!! Thank you for the assistance. I may be reaching out again before this is done 🙂
Here's what I did to get it working...
$ActionsBody = @"
{
"actions": [
{
"name": "0",
"request": true,
"forward": true,
"pool": "/Common/pool_test"
}
],
"conditions": [
{
"name":"0",
"request": true,
"httpHost": true,
"equals": true,
"values": [
"www.mydomain.net"
]
}
]
}
"@
Invoke-RestMethod -Uri https://$url/mgmt/tm/ltm/policy/~Common~Drafts~$Policy/rules/Testing -Method PUT -Headers $Header -Body $ActionsBody -ContentType 'application/json'
02-Jul-2020 09:43
Yes, now I test it right.
We forgot that array collections: 😕
$ActionsBody = @{
actions = @( @{
name = "0"
request = $true
forward = $true
pool = "/Common/pool_teste"
} )
conditions = @( @{
name = "0"
request = $true
httpHost = $true
equals = $true
values = @("www.mydomain.net")
} )
}
Invoke-RestMethod -Uri https://$url/mgmt/tm/ltm/policy/~Common~Drafts~$Policy/rules/Testing -Method PUT -Headers $Header -Body (ConvertTo-Json $ActionsBody -Depth 3) -ContentType 'application/json'