How to FortiManager API?

Objects Management

Contents

3. Objects Management#

This section is about managing the objects that can be targetted using the following JSON RPC url:

/pm/config/adom/{adom}/obj/{path_to_object}
/pm/config/global/obj/{path_to_object}

3.1. How to reference objects when names have special characters?#

It is required to escape the special character using the \\ (double back-slash) notation.

For instance to update the Net_10.0.0.0/18 (where / is the special character) located in the root ADOM:

{
  "id": 4,
  "method": "update",
  "params": [
    {
      "url": "pm/config/adom/root/obj/firewall/address/Net_10.0.0.0\\/18",
      "data": {
        "subnet": "10.0.0.0/255.255.255.0",
      }
    }
  ],
  "session": "{{session}}",
}

3.2. Metadata#

Metadata object has been introduced in FortiManager 7.2.0 to replace the Meta fields.

3.2.1. How to add a metadata?#

We add metadata site_id with default value 0 in ADOM root:

REQUEST:

{
  "id": 3,
  "method": "add",
  "params": [
    {
      "data": {
        "name": "site_id",
        "value": "0"
      },
      "url": "/pm/config/adom/root/obj/fmg/variable"
    }
  ],
  "session": "uY6pkBTKxePxylSULcalT0qJWJ2Wpot75EMoQurXIk1lInRrfOpUw2/Ry6L2H/AGeKyr75k6i5x4xSeg4qN/Gg=="
}

Warning

  • The value attribute has to be set with a string.

RESPONSE:

{
  "id": 3,
  "result": [
    {
      "data": {
        "name": "site_id"
      },
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/root/obj/fmg/variable"
    }
  ]
}

3.2.2. How to delete a metadata?#

We delete metadata site_id from ADOM root:

REQUEST:

{
  "id": 3,
  "method": "delete",
  "params": [
    {
      "url": "/pm/config/adom/root/obj/fmg/variable/site_id"
    }
  ],
  "session": "VhmbOYvjWhsmSXtHHkp1298dkvfaAt7cUQbUBLKqpTfN4/oqntbOLxtQvYnIhvtTdm9Xa8mlv+U5NxVKDJvd9Q=="
}

RESPONSE:

{
  "id": 3,
  "result": [
    {
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/root/obj/fmg/variable/site_id"
    }
  ]
}

3.2.3. How to assign a metadata to devices?#

  1. For a single device:

    • We add a per-device mapping to metadata site_id for device site_001 in ADOM root. The value will be 1.

      REQUEST:

      {
        "id": 3,
        "method": "add",
        "params": [
          {
            "data": [
              {
                "_scope": [
                  {
                    "name": "site_001",
                    "vdom": "global"
                  }
                ],
                "value": "1"
              }
            ],
            "url": "/pm/config/adom/root/obj/fmg/variable/site_id/dynamic_mapping"
          }
        ],
        "session": "1UFghhT0KF8dDRHAhCfP87MqAVZOwfDpOFyo1wLKLhYWfrNaMZPnkvcAKtmZUw6a9CHYVTRblay/iQjddRTrNg=="
      }
      

      Warning

      • The value attribute has to be set with a string.

      RESPONSE:

      {
        "id": 3,
        "result": [
          {
            "data": {
              "_scope": null
            },
            "status": {
              "code": 0,
              "message": "OK"
            },
            "url": "/pm/config/adom/root/obj/fmg/variable/site_id/dynamic_mapping"
          }
        ]
      }
      
  2. For multiple devices

    • We add per-device mapping to metadata site_id for devices site_002 and site_003, and their respective VDOM root for both, in ADOM root. New values will be 2 and 3 respectively:

      REQUEST:

      {
        "id": 3,
        "method": "add",
        "params": [
          {
            "data": [
              {
                "_scope": [
                  {
                    "name": "site_002",
                    "vdom": "root"
                  }
                ],
                "value": "2"
              },
              {
                "_scope": [
                  {
                    "name": "site_003",
                    "vdom": "root"
                  }
                ],
                "value": "3"
              }
            ],
            "url": "/pm/config/adom/root/obj/fmg/variable/site_id/dynamic_mapping"
          }
        ],
        "session": "3xU3/QYJvng9a91JN0Ivzi0XY6RPyvrYxtfa4xPjJTKwvVQQAs0VG9aTjf6ozgqEYcCMF7xvhRKe27J43btpEQ=="
      }
      

      Warning

      • The value attribute has to be set with a string.

      RESPONSE:

      {
        "id": 3,
        "result": [
          {
            "status": {
              "code": 0,
              "message": "OK"
            },
            "url": "/pm/config/adom/root/obj/fmg/variable/site_id/dynamic_mapping"
          }
        ]
      }
      

3.2.4. How to assign metadatas at Model Device creation time?#

It can be exposed by using the following FortiManager CLI debug command:

diagnose debug service dvmcmd 255
diagnose debug
{
  "client": "gui json:23235",
  "id": "57337fc8-5029-4458-b100-18cddddb707b",
  "keep_session_idle": 1,
  "method": "exec",
  "params": [
    {
      "data": {
        "add-dev-list": [
          {
            "_platform": "FortiGate-VM64-KVM",
            "adm_pass": "******",
            "adm_usr": "admin",
            "desc": "Model device",
            "device action": "add_model",
            "device blueprint": "BRANCHES",
            "extra commands": [
              {
                "id": 1,
                "method": "set",
                "params": [
                  {
                    "data": {
                      "_scope": {
                        "name": "BRANCH_03",
                        "vdom": "global",
                        "vdom_oid": 1
                      },
                      "value": "10.200.1.3"
                    },
                    "url": "pm/config/adom/DEMO/obj/fmg/variable/BGP_LOOPBACK/dynamic_mapping"
                  }
                ]
              },
              {
                "id": 1,
                "method": "set",
                "params": [
                  {
                    "data": {
                      "_scope": {
                        "name": "BRANCH_03",
                        "vdom": "global",
                        "vdom_oid": 1
                      },
                      "value": ""
                    },
                    "url": "pm/config/adom/DEMO/obj/fmg/variable/INET1_IP/dynamic_mapping"
                  }
                ]
              },
              {
                "id": 1,
                "method": "set",
                "params": [
                  {
                    "data": {
                      "_scope": {
                        "name": "BRANCH_03",
                        "vdom": "global",
                        "vdom_oid": 1
                      },
                      "value": ""
                    },
                    "url": "pm/config/adom/DEMO/obj/fmg/variable/INET2_IP/dynamic_mapping"
                  }
                ]
              },
              {
                "id": 1,
                "method": "set",
                "params": [
                  {
                    "data": {
                      "_scope": {
                        "name": "BRANCH_03",
                        "vdom": "global",
                        "vdom_oid": 1
                      },
                      "value": "10.71.144.1/24"
                    },
                    "url": "pm/config/adom/DEMO/obj/fmg/variable/MPLS_IP/dynamic_mapping"
                  }
                ]
              },
              {
                "id": 1,
                "method": "set",
                "params": [
                  {
                    "data": {
                      "_scope": {
                        "name": "BRANCH_03",
                        "vdom": "global",
                        "vdom_oid": 1
                      },
                      "value": "10.0.3.1/24"
                    },
                    "url": "pm/config/adom/DEMO/obj/fmg/variable/LAN_IP/dynamic_mapping"
                  }
                ]
              },
              {
                "id": 1,
                "method": "set",
                "params": [
                  {
                    "data": {
                      "_scope": {
                        "name": "BRANCH_03",
                        "vdom": "global",
                        "vdom_oid": 1
                      },
                      "value": "10.0.31.1/24"
                    },
                    "url": "pm/config/adom/DEMO/obj/fmg/variable/VLAN1_IP/dynamic_mapping"
                  }
                ]
              },
              {
                "id": 1,
                "method": "set",
                "params": [
                  {
                    "data": {
                      "_scope": {
                        "name": "BRANCH_03",
                        "vdom": "global",
                        "vdom_oid": 1
                      },
                      "value": "10.0.32.1/24"
                    },
                    "url": "pm/config/adom/DEMO/obj/fmg/variable/VLAN2_IP/dynamic_mapping"
                  }
                ]
              },
              {
                "id": 1,
                "method": "set",
                "params": [
                  {
                    "data": {
                      "_scope": {
                        "name": "BRANCH_03",
                        "vdom": "global",
                        "vdom_oid": 1
                      },
                      "value": "10.0.33.1/24"
                    },
                    "url": "pm/config/adom/DEMO/obj/fmg/variable/VLAN3_IP/dynamic_mapping"
                  }
                ]
              },
              {
                "id": 1,
                "method": "set",
                "params": [
                  {
                    "data": {
                      "_scope": {
                        "name": "BRANCH_03",
                        "vdom": "global",
                        "vdom_oid": 1
                      },
                      "value": "172.16.31.42/24"
                    },
                    "url": "pm/config/adom/DEMO/obj/fmg/variable/OOB/dynamic_mapping"
                  }
                ]
              },
              {
                "id": 1,
                "method": "set",
                "params": [
                  {
                    "data": {
                      "_scope": {
                        "name": "BRANCH_03",
                        "vdom": "global",
                        "vdom_oid": 1
                      },
                      "value": "140"
                    },
                    "url": "pm/config/adom/DEMO/obj/fmg/variable/VLAN_BASE/dynamic_mapping"
                  }
                ]
              }
            ],
            "faz.perm": 15,
            "faz.quota": 0,
            "groups": [
              "BRANCHES"
            ],
            "is_vm": true,
            "mgmt_mode": 3,
            "mr": 2,
            "name": "BRANCH_03",
            "os_type": 0,
            "os_ver": 7,
            "sn": "FGVM08TM23000464"
          }
        ],
        "adom": "DEMO",
        "flags": [
          "create_task",
          "nonblocking",
          "log_dev"
        ]
      },
      "target start": 2,
      "url": "/dvm/cmd/add/dev-list"
    }
  ],
  "session": 52098
}

3.2.5. How to unassign a metadata?#

  • We delete per-device mapping for device site_001 in ADOM root

    REQUEST:

    {
      "id": 3,
      "method": "delete",
      "params": [
        {
          "url": "/pm/config/adom/root/obj/fmg/variable/site_id/dynamic_mapping/site_001/global"
        }
      ],
      "session": "DeDg35oRLquI5LoY6jegKxzO30MuvijlQofAK7GSsVE2aHhdemGk7qmscZp9FlvFPsadu3fO9nyfhYf9asv4sA=="
    }
    

    RESPONSE:

    {
      "id": 3,
      "result": [
        {
          "status": {
            "code": 0,
            "message": "OK"
          },
          "url": "/pm/config/adom/root/obj/fmg/variable/site_id/dynamic_mapping/site_001/global"
        }
      ]
    }
    

3.2.6. How to replace assigned device with another one?#

In ADOM root, we have a metadata site_id assigned to device site_003 scope global with value 3:

REQUEST:

{
  "id": 3,
  "method": "get",
  "params": [
    {
      "url": "/pm/config/adom/root/obj/fmg/variable/site_id/dynamic_mapping/site_003/global"
    }
  ],
  "session": "lSwBO+josIsWGTLgfPunWDUhI1yhnYXmsOexJszAjOrZgrAwcgSHmaLUcz8kgcwa+DTFdiPmJPQd6p6uhbDBRA=="
}

RESPONSE:

{
  "id": 3,
  "result": [
    {
      "data": {
        "_scope": [
          {
            "name": "site_003",
            "vdom": "global"
          }
        ],
        "oid": 3989,
        "value": "3"
      },
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/root/obj/fmg/variable/site_id/dynamic_mapping/site_003/global"
    }
  ]
}

We replace devicee site_003 scope global with device site_002 vdom root. Both value and oid shouldn’t be modified:

REQUEST:

{
  "id": 3,
  "method": "set",
  "params": [
    {
      "data": [
        {
          "name": "site_002",
          "vdom": "root"
        }
      ],
      "url": "/pm/config/adom/root/obj/fmg/variable/site_id/dynamic_mapping/site_003/global/_scope"
    }
  ],
  "session": "Wx30e3o21dbA577ZQC4uEWr2FxdYJNycLfL2JGZ8oa9x7p7/0W+catuBCyXJB6Rq3Y0vDQSWr4UIOpig3Q6TUzawM01Jsanb"
}

RESPONSE:

{
  "id": 3,
  "result": [
    {
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/root/obj/fmg/variable/site_id/dynamic_mapping/site_003/global/_scope"
    }
  ]
}

We can double check: both value and oid are still with same value as before the replace operation:

REQUEST:

{
  "id": 3,
  "method": "get",
  "params": [
    {
      "url": "/pm/config/adom/root/obj/fmg/variable/site_id/dynamic_mapping/site_002/root"
    }
  ],
  "session": "GDbXiJQeLFHJn353tBpV8dTv0j/YBBHvjN/diKqSn6SNkY9H2HUy+5tResAiNQgLGOGX2HXMaUwLJJQ57t0Jwg=="
}

RESPONSE:

{
  "id": 3,
  "result": [
    {
      "data": {
        "_scope": [
          {
            "name": "site_002",
            "vdom": "root"
          }
        ],
        "oid": 3989,
        "value": "3"
      },
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/root/obj/fmg/variable/site_id/dynamic_mapping/site_002/root"
    }
  ]
}

3.2.7. How to get the value of a metadata for a specific device/vdom?#

We get the value of metadata site_id for device site_001 and its global scope from ADOM root:

REQUEST:

{
  "id": 3,
  "method": "get",
  "params": [
    {
      "url": "/pm/config/adom/root/obj/fmg/variable/site_id/dynamic_mapping/site_001/global"
    }
  ],
  "session": "iQ+NZu8QXUBKYgM9xUrzqCoHKx3l5SpClqociYCkl/b8GQNN2x9YReV6BsmIMiqgJs3rLpyvNjcBzu021YPh7A==",
  "verbose": 1
}

RESPONSE:

{
  "id": 3,
  "result": [
    {
      "data": {
        "_scope": [
          {
            "name": "site_001",
            "vdom": "global"
          }
        ],
        "oid": 3934,
        "value": "1"
      },
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/root/obj/fmg/variable/site_id/dynamic_mapping/site_001/global"
    }
  ]
}

We get the value of metadata site_id for device site_002 and its VDOM root from ADOM root:

REQUEST:

{
  "id": 3,
  "method": "get",
  "params": [
    {
      "url": "/pm/config/adom/root/obj/fmg/variable/site_id/dynamic_mapping/site_002/root"
    }
  ],
  "session": "iQ+NZu8QXUDbEN3utJr/yA3FEKeC10AoEByuOehZ/eQhLjBl0boh2U9MCh8eI78aNTOIV+3SbjGXg+D0MkSgXQ==",
  "verbose": 1
}

RESPONSE:

{
  "id": 3,
  "result": [
    {
      "data": {
        "_scope": [
          {
            "name": "site_002",
            "vdom": "root"
          }
        ],
        "oid": 3745,
        "value": "2"
      },
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/root/obj/fmg/variable/site_id/dynamic_mapping/site_002/root"
    }
  ]
}

3.2.8. How to set multiple metadatas for one device?#

It is possible to use a single FortiManager JSON RPC API request.

The following example set the var_01 and var_02 metadata variables from the dc_amer ADOM for the dev_02 managed device:

REQUEST:

{
  "id": 3,
  "method": "add",
  "params": [
    {
      "data": {
        "_scope": [
          {
            "name": "dev_02",
            "vdom": "global"
          }
        ],
        "value": "var_01_dev_02"
      },
      "url": "/pm/config/adom/dc_amer/obj/fmg/variable/var_01/dynamic_mapping"
    },
    {
      "data": {
        "_scope": [
          {
            "name": "dev_02",
            "vdom": "global"
          }
        ],
        "value": "var_02_dev_02"
      },
      "url": "/pm/config/adom/dc_amer/obj/fmg/variable/var_02/dynamic_mapping"
    }
  ],
  "session": "tVbqoJKblP/y6kd7B81wXl0qgg/40nzI5Rh4ggoUVaE8b0KT0+xw/gd3/MzcufezS749zd+L7MVIMQDxqNR/rg=="
}

RESPONSE:

{
  "id": 3,
  "result": [
    {
      "data": {
        "_scope": [
          {
            "name": "dev_02",
            "vdom": "global"
          }
        ]
      },
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/dc_amer/obj/fmg/variable/var_01/dynamic_mapping"
    },
    {
      "data": {
        "_scope": [
          {
            "name": "dev_02",
            "vdom": "global"
          }
        ]
      },
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/dc_amer/obj/fmg/variable/var_02/dynamic_mapping"
    }
  ]
}

Note

  • Of course, existing per-device mappings for the var_01 and var_02 metadata variables are preserved.

3.2.9. How to assign a global metadata?#

Global ADOM is having the global metadata g_hostname.

To assign it to ADOM root, adom_70_001 and adom_72_001:

REQUEST:

{
  "id": 3,
  "method": "exec",
  "params": [
    {
      "data": {
        "adom": "global",
        "category": 3200,
        "flags": "none",
        "objs": [
          "g_hostname"
        ],
        "scope": [
          {
            "adom": "root"
          },
          {
            "adom": "adom_70_001"
          },
          {
            "adom": "adom_72_001"
          }
        ],
        "target": [
          {
            "adom": "root"
          },
          {
            "adom": "adom_70_001"
          },
          {
            "adom": "adom_72_001"
          }
        ]
      },
      "url": "/securityconsole/assign/objs"
    }
  ],
  "session": "tshDOEgzpF26vjcMeyDha3MSpwg570lSrbKirRk1wkdLIToAZOgkWOw6xlIhawjUoMKkOZNAS49AQqiRWMzdtyZHSQg1POJs"
}

where category is the number of the table fmg variable.

You can get this number by issuing following command:

execute fmpolicy print-adom-object Global ?

In the output, you will see this line:

[...]
3200 "fmg variable"
[...]

RESPONSE:

{
  "id": 3,
  "result": [
    {
      "data": {
        "task": 54
      },
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/securityconsole/assign/objs"
    }
  ]
}

3.3. Firewall Address#

3.3.1. How to add a FQDN firewall address?#

To add FQDN www.foobar.com in ADOM adom_70_001:

REQUEST:

{
  "id": 3,
  "method": "add",
  "params": [
    {
      "data": {
        "color": 2,
        "fqdn": "www.foobar.com",
        "name": "fqdn_001",
        "type": "fqdn"
      },
      "url": "/pm/config/adom/adom_70_001/obj/firewall/address"
    }
  ],
  "session": "FhdDcem5V4cjJZeGggJ36dn5fME4nxr4rkA0zojtu+c31+wGhWl2zhhhE2hyP/MAXWQQzNE1yUgQOrJ3eTH7SQ=="
}

RESPONSE:

{
  "id": 3,
  "result": [
    {
      "data": {
        "name": "fqdn_001"
      },
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/adom_70_001/obj/firewall/address"
    }
  ]
}

3.4. Firewall Address Groups#

3.4.1. How to add a single member#

We add firewall address host_004 in the existing address group foobar from ADOM adom_dc2:

REQUEST:

{
  "id": 3,
  "method": "add",
  "params": [
    {
      "data": [
        "host_004"
      ],
      "url": "/pm/config/adom/adom_dc2/obj/firewall/addrgrp/foobar/member"
    }
  ],
  "session": "mZMkY72ZIYcs8QInB0h5CUILmCKWCesbvxXJ3P/t+JSrzBh32BV/HvCU7BNMp4GLe8/5vO1qNAoRlsSytXUlTw=="
}

RESPONSE:

{
  "id": 3,
  "result": [
    {
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/adom_dc2/obj/firewall/addrgrp/foobar/member"
    }
  ]
}

3.4.2. How to delete a single member#

We delete firewall address host_004 from the existing address group foobar from ADOM adom_dc2:

REQUEST:

{
  "id": 3,
  "method": "delete",
  "params": [
    {
      "data": [
        "host_004"
      ],
      "url": "/pm/config/adom/adom_dc2/obj/firewall/addrgrp/foobar/member"
    }
  ],
  "session": "5uNGBXEMc+cNXjSlx6RuyxE623Nul3hGTCEgeA7pONsNhMMEL1lxCUG7q2TVfnhD0BZiwMg+CgKpWuVY2k0oew=="
}

RESPONSE:

{
  "id": 3,
  "result": [
    {
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/adom_dc2/obj/firewall/addrgrp/foobar/member"
    }
  ]
}

3.4.3. How to delete all members?#

Note

  • You can delete all members because since FortiOS 7.2.0 (Internal Reference #0769154), you can operate an empty firewall addrgrp object

3.4.3.1. Using the unset method#

The following example shows how to delete all members from othe grp_001 firewall addrgrp in the demo ADOM using the unset method:

{
  "id": 3,
  "method": "unset",
  "params": [
    {
      "url": "/pm/config/adom/demo/obj/firewall/addrgrp/grp_001/member"
    }
  ],
  "session": "{{session}}"
}
{
  "id": 3,
  "result": [
    {
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/demo/obj/firewall/addrgrp/grp_001/member"
    }
  ]
}

3.4.3.2. Using the unset attrs#

The following example shows how to delete all members from othe grp_001 firewall addrgrp in the demo ADOM using the unset attrs described in How to unset a specific attribute?:

{
  "id": 3,
  "method": "set",
  "params": [
    {
      "data": {
        "unset attrs": [
          "member"
        ]
      },
      "url": "/pm/config/adom/demo/obj/firewall/addrgrp/grp_001"
    }
  ],
  "session": "{{session}}"
}
{
  "id": 3,
  "result": [
    {
      "data": {
        "name": "grp_001"
      },
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/demo/obj/firewall/addrgrp/grp_001"
    }
  ]
}

3.5. Wildcard FQDN#

3.5.1. How to add a wildcard FQDN?#

To add wilcard FQDN *.foobar.* to ADOM adom_70_001:

REQUEST:

{
  "id": 3,
  "method": "add",
  "params": [
    {
      "data": {
        "color": 3,
        "name": "w_fqdn_001",
        "wildcard-fqdn": "*.foobar.*",
      },
      "url": "/pm/config/adom/adom_70_001/obj/firewall/wildcard-fqdn/custom"
    }
  ],
  "session": "/CPDFD77zdvbfmX5tI0OwZ6mEha6Zcfsn1qPaITMmr43uysUgPlNBK5TgUIXFYQcoQXwF0w2oh1XcKRUnB2BMg=="
}

RESPONSE:

{
  "id": 3,
  "result": [
    {
      "data": {
        "name": "w_fqdn_001"
      },
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/adom_70_001/obj/firewall/wildcard-fqdn/custom"
    }
  ]
}

3.6. Objects default values#

3.6.1. How to get the default values for a firewall address?#

REQUEST:

{
  "id": 1,
  "jsonrpc": "1.0",
  "method": "get",
  "params": [
    {
      "object template": 1,
      "url": "/pm/config/adom/DB/obj/firewall/address"
    }
  ],
  "session": "HKERCCqx6ximKXlkWN7lxWIgqagVqpj0xXiJtFtYrpiLIL7X3nCuIdlnZw83N+N3JO95oUOOCIwE+emXMuLvcPvKXNHsVYSN",
  "verbose": 1
}

3.7. How to bulk add objects?#

You have two methods:

  • params multi-plexing

  • data multi-plexing

3.7.1. params multi-plexing#

REQUEST:

{
  "id": 1,
  "jsonrpc": "1.0",
  "method": "add",
  "params": [
    {
      "data": {
        "name": "test_004",
        "subnet": [
          "10.0.0.4",
          "255.255.255.0"
        ]
      },
      "url": "/pm/config/adom/DEMO_008/obj/firewall/address"
    },
    {
      "data": {
        "name": "test_005",
        "subnet": [
          "10.0.0.5",
          "255.255.255.0"
        ]
      },
      "url": "/pm/config/adom/DEMO_008/obj/firewall/address"
    },
    {
      "data": {
        "name": "test_006",
        "subnet": [
          "10.0.0.6",
          "255.255.255.0"
        ]
      },
      "url": "/pm/config/adom/DEMO_008/obj/firewall/address"
    }
  ],
  "session": "H4bqANWVw4+9ChxkRYdNfdtu4kE+5emeSojgay0fOghSwAPaFuzoBSZHjcvWc6l3TanYih4q9QktzVvLNTdpzA==",
  "verbose": 1
}

RESPONSE:

{
  "id": 1,
  "result": [
    {
      "data": {
        "name": "test_004"
      },
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/DEMO_008/obj/firewall/address"
    },
    {
      "data": {
        "name": "test_005"
      },
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/DEMO_008/obj/firewall/address"
    },
    {
      "data": {
        "name": "test_006"
      },
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/DEMO_008/obj/firewall/address"
    }
  ]
}

3.7.2. data multi-plexing#

REQUEST:

{
  "id": 1,
  "jsonrpc": "1.0",
  "method": "add",
  "params": [
    {
      "data": [
        {
          "name": "test_001",
          "subnet": [
            "10.0.0.1",
            "255.255.255.0"
          ]
        },
        {
          "name": "test_002",
          "subnet": [
            "10.0.0.2",
            "255.255.255.0"
          ]
        },
        {
          "name": "test_003",
          "subnet": [
            "10.0.0.3",
            "255.255.255.0"
          ]
        }
      ],
      "url": "/pm/config/adom/DEMO_008/obj/firewall/address"
    }
  ],
  "session": "31rAPPvgsYtaqwXnlwKZJrJQHff1V5hbfwj9lB62868KC1n73fF739Z+wTP+J5CoTxjKSWE8TqY7mTHyFovW7w==",
  "verbose": 1
}

RESPONSE:

{
  "id": 1,
  "result": [
    {
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/DEMO_008/obj/firewall/address"
    }
  ]
}

3.8. Normalized Interfaces#

3.8.1. How to create a normalized interface?#

REQUEST:

{
  "id": 1,
  "jsonrpc": "1.0",
  "method": "add",
  "params": [
    {
        "data": {
            "color": 2,
            "default-mapping": "enable",
            "defmap-intf": "ul_isp1",
            "description": "Underlay over ISP #1",
            "dynamic_mapping": [
                {
                    "_scope": [
                        {
                            "name": "dut_fgt_2",
                            "vdom": "root"
                        }
                    ],
                    "local-intf": [
                        "port1"
                    ]
                }
            ],
            "name": "ul_isp1",
            "platform_mapping": [
                {
                    "intf-zone": "ul_isp1",
                    "name": "FortiGate-100F"
                }
            ]
        },
        "url": "/pm/config/adom/{{adom}}/obj/dynamic/interface/ul_isp1"
    }
  ],
  "session": "{{session_id}}",
  "verbose": 1
}

RESPONSE:

{
  "id": 1,
  "result": [
    {
      "data": {
        "name": "ul_isp1"
      },
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/knock_06999/obj/dynamic/interface/ul_isp1"
    }
  ]
}

3.8.2. How to add a new per-platform mapping to an existing Normalized Interface?#

REQUEST:

{
  "id": 3,
  "method": "add",
  "params": [
    {
      "data": {
        "intf-zone": "ol_isp2",
        "name": "FortiGate-40F"
      },
      "url": "/pm/config/adom/root/obj/dynamic/interface/ol_isp2/platform_mapping"
    }
  ],
  "session": "6hngsu9e2X+JBkpzxVIdWYPqLeYactJjmyyXeGkpkB/BlzGI8R9ynUPSP2wKFH5rTcijjR4+XBXWfliD7ichEg=="
}

RESPONSE:

{
  "id": 3,
  "result": [
    {
      "data": {
        "name": "FortiGate-40F"
      },
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/root/obj/dynamic/interface/ol_isp2/platform_mapping"
    }
  ]
}

3.8.3. How to get the normalized interfaces with a per-device mapping set for a specific device?#

The following example shows how to get the list of normalized interfaces with a per-device mapping for the dut_fgt_03 device and its root VDOM:

{
  "id": "1",
  "method": "get",
  "params":[
    {
      "url": "pm/config/adom/{{adom}}/obj/dynamic/interface",
      "fields": ["name"],
      "subfetch filter": 1,
      "sub fetch": {
        "dynamic_mapping": {
          "fields": ["_scope", "local_intf"],
          "subfetch count": ["==", 1],
          "scope member": [
            {
              "name": "dut_fgt_03",
              "vdom": "root"
            }
          ]
        },
        "platform_mapping": {
          "subfetch hidden": 1
        }
      }
    }
  ],
  "session": "{{session}}"
}

3.8.4. How to delete an existing per-platform mapping?#

REQUEST:

{
  "id": 3,
  "method": "delete",
  "params": [
    {
      "url": "/pm/config/adom/root/obj/dynamic/interface/ol_isp2/platform_mapping/FortiGate-40F"
    }
  ],
  "session": "vfIpN+LiUYGkHWcdTYcEe5RtIhDuIlw/42o9EsZ1KwNCHmSnytwa+cmTHGSJwEyYtencb3kLmFdq6AX5PK2FxQ=="
}

RESPONSE:

{
  "id": 3,
  "result": [
    {
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/root/obj/dynamic/interface/ol_isp2/platform_mapping/FortiGate-40F"
    }
  ]
}

3.9. How to get firewall addgrp members along with their details?#

We can use the expand datasrc attribute.

We’re getting the member elements of our grp_003 address group:

REQUEST:

{
  "id": 1,
  "jsonrpc": "1.0",
  "method": "get",
  "params": [
    {
      "expand datasrc": [
        {
          "datasrc": [
            {
              "fields": [
                "name",
                "subnet"
              ],
              "obj type": "firewall address"
            },
            {
              "fields": [
                "name",
                "member"
              ],
              "obj type": "firewall addrgrp"
            }
          ],
          "name": "member"
        }
      ],
      "filter": [
        "name",
        "==",
        "grp_003"
      ],
      "url": "/pm/config/adom/DEMO/obj/firewall/addrgrp"
    }
  ],
  "session": "mnvLPffV1QUzdQkAPo9dv5ysdS0wzcvhZMX1w8Hv9Q07XYWtTqeClXEYhLN6e0aBvfuowZ7x/2FHORh7qFs5iw==",
  "verbose": 1
}

RESPONSE:

{
  "id": 1,
  "result": [
    {
      "data": [
        {
          "allow-routing": "disable",
          "color": 0,
          "comment": "",
          "dynamic_mapping": null,
          "exclude": "disable",
          "exclude-member": [],
          "member": [
            {
              "name": "host_005",
              "obj type": "firewall address",
              "subnet": [
                "10.0.0.5",
                "255.255.255.255"
              ]
            },
            {
              "name": "host_006",
              "obj type": "firewall address",
              "subnet": [
                "10.0.0.6",
                "255.255.255.255"
              ]
            },
            {
              "member": [
                "host_001",
                "host_002"
              ],
              "name": "grp_001",
              "obj type": "firewall addrgrp"
            },
            {
              "member": [
                "host_003",
                "host_004"
              ],
              "name": "grp_002",
              "obj type": "firewall addrgrp"
            }
          ],
          "name": "grp_003",
          "tagging": null,
          "uuid": "c5097fe2-cbf3-51ea-94c7-4543af3302a3",
          "visibility": "enable"
        }
      ],
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/DEMO/obj/firewall/addrgrp"
    }
  ]
}

3.10. How to get the full ADOM database objects syntax?#

Caught in #0607071.

REQUEST:

{
  "id": 1,
  "method": "get",
  "params": [
    {
      "url": "pm/config/adom/root/obj",
      "option": "syntax"
    }
  ]
}

Note

Option syntax is described in section [TODO].

3.11. Internet Service Objects#

3.11.1. How to get the regions that can be used in a Geographic Based Internet Service object?#

To get the regions that could be used to define a geographic based internet service object:

REQUEST:

{
  "id": 3,
  "method": "get",
  "params": [
    {
      "url": "/pm/config/adom/root/_fdsdb/internet-service/region"
    }
  ],
  "session": "cE/JiIBEdO4fWbjUPcrkyTCxuNnT6IGv3NKKHbgXRdSLwphqWRCYRu0M1ZZq4iwMhbQgft8evZlgokRV1bukNg==",
  "verbose": 1
}

RESPONSE:

{
  "id": 3,
  "result": [
    {
      "data": [
        {
          "id": 2,
          "name": "Aargau",
          "subarea": "34,1495,2468,3282,13226,13956,15459,17315,19920"
        },
        {
          "id": 3,
          "name": "Abidjan",
          "subarea": "73"
        },
        {
          "id": 4,
          "name": "Abitibi-OuestQuebec",
          "subarea": "12575"
        },
        {
          "...": "..."
        },
        {
          "id": 2141,
          "name": "Zonguldak",
          "subarea": "4207,27249"
        },
        {
          "id": 2142,
          "name": "Zulia",
          "subarea": "3575,4819,14422,21046"
        },
        {
          "id": 2143,
          "name": "Zurich",
          "subarea": "1836,6324,6902,7317,14740,17510,17737,18456,19790,20490,20503,21627,24895,25812,26600,27285"
        }
      ],
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/root/_fdsdb/internet-service/region",
      "version": "7.2557"
    }
  ]
}

3.11.2. How to get the countries that can be used in a Geographic Based Internet Service object?#

To get the countries that could be used to define a geographic based internet service object:

REQUEST:

{
  "id": 3,
  "method": "get",
  "params": [
    {
      "url": "/pm/config/adom/root/_fdsdb/internet-service/country"
    }
  ],
  "session": "B3w+I+2XazWeTp7nDKnycudpE7slpKntuw0BgsXlxu7cWi7qQyCd4lDUoWHdrRh/lSMLhVTh1cWdYTtJBY8BQQ==",
  "verbose": 1
}

RESPONSE:

{
  "id": 3,
  "result": [
    {
      "data": [
        {
          "id": 4,
          "name": "Afghanistan",
          "subarea": "826,65535"
        },
        {
          "id": 248,
          "name": "Aland Islands",
          "subarea": "65535"
        },
        {
          "id": 8,
          "name": "Albania",
          "subarea": "206,478,505,527,561,607,951,978,1048,1719,1892,2045"
        },
        {
          "...": "...",
        },
        {
          "id": 887,
          "name": "Yemen",
          "subarea": "309,65535"
        },
        {
          "id": 894,
          "name": "Zambia",
          "subarea": "431,1097,65535"
        },
        {
          "id": 716,
          "name": "Zimbabwe",
          "subarea": "264,671,1152,2193,65535"
        }
      ],
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/root/_fdsdb/internet-service/country",
      "version": "7.2557"
    }
  ]
}

3.11.3. How to get the cities that can be used in a Geographic Based Internet Service object?#

To get the cities that could be used to define a geographic based internet service object:

REQUEST:

{
  "id": 3,
  "method": "get",
  "params": [
    {
      "url": "/pm/config/adom/root/_fdsdb/internet-service/city"
    }
  ],
  "session": "bRq2VA27Gi9fNaR3QpUn0yOhSiAqYDJwCvoz2GE3Mdiml2cBOfV7C/b4kCfMz5ObnBiM52DeJwUhnvGuLrNRzg==",
  "verbose": 1
}

RESPONSE:

{
  "id": 3,
  "result": [
    {
      "data": [
        {
          "id": 1,
          "name": "'s Hertogenbosch",
          "subarea": ""
        },
        {
          "id": 7,
          "name": "'s-Heer Hendrikskinderen",
          "subarea": ""
        },
        {
          "id": 13,
          "name": "3 de Mayo",
          "subarea": ""
        },
        {
          "...": "...",
        },
        {
          "id": 27318,
          "name": "`Ayn al Fijah",
          "subarea": ""
        },
        {
          "id": 27319,
          "name": "`Ayn ash Sharqiyah",
          "subarea": ""
        },
        {
          "id": 29175,
          "name": "`Uqayribat",
          "subarea": ""
        }
      ],
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/root/_fdsdb/internet-service/city",
      "version": "7.2557"
    }
  ]
}

3.11.4. How to get the list of the Internet Service objects?#

Caught in #0622870.

REQUEST:

{
  "id": "22a9fecf-7838-4795-a838-1633321197c2",
  "method": "get",
  "params": [
    {
      "url": "pm/config/adom/root/_fdsdb/internet-service",
      "option": [
        "get used",
        "get flags",
        "get devobj mapping",
        "get meta",
        "extra info",
        "no loadsub",
        "get reserved"
      ]
    }
  ]
}

and

REQUEST:

{
  "id": "99a913f3-0177-463c-b3ce-04eabf9c0100",
  "method": "get",
  "params": [
    {
      "url": "pm/config/adom/640/obj/firewall/internet-service-name",
      "option": [
        "get used",
        "get flags",
        "get devobj mapping",
        "get meta",
        "extra info",
        "no loadsub"
      ]
    }
  ]
}

But according to the #0622870, it is better to consider the method explained in section [TODO] (datasrc).

3.12. Operations on objects#

3.12.1. Cloning objects#

3.12.1.1. How to clone a firewall address?#

REQUEST:

{
  "id": 1,
  "jsonrpc": "1.0",
  "method": "clone",
  "params": [
    {
      "data": {
        "name": "clone_host_001"
      },
      "url": "/pm/config/adom/DEMO_013/obj/firewall/address/host_001"
    }
  ],
  "session": "/FPLhY0rgXbpuZYz3TpcGtHQirT0ZHF09ILBV0ZrsWs2Knebq+5+CZ0fXejmyNWVqUm9Aftknb1biLL2JwiyXw==",
  "verbose": 1
}

RESPONSE:

{
  "id": 1,
  "result": [
    {
      "data": {
        "name": "clone_host_001"
      },
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/DEMO_013/obj/firewall/address/host_001"
    }
  ]
}

3.12.2. Filtering objects#

Getting an object table could generate a lot of output data.

Furthermore, most of the time, you’re only interested by a sub-part of that table if not by a single entry.

This is what you can achieve by filtering objects.

3.12.2.1. The contain operator#

To get firewall address groups containing member host_001:

{
  "id": 3,
  "method": "get",
  "params": [
    {
      "fields": [
        "name",
        "member"
      ],
      "filter": [
        "member",
        "contain",
        "host_001"
      ],
      "loadsub": 0,
      "url": "/pm/config/adom/dc_amer/obj/firewall/addrgrp"
    }
  ],
  "session": "{{ session }}"
}

3.12.2.2. How to filter firewall address according to their IPs?#

Caught in #0363496.

  • To retrieve firewall address included in a specific IP address

    We can use the <= comparison operator.

    In the below example, we want all firewall addresses belonging to IP subnet 3.14.142.0/24:

    REQUEST:

    {
      "id": 1,
      "jsonrpc": "1.0",
      "method": "get",
      "params": [
        {
          "fields": [
            "name",
            "subnet"
          ],
          "filter": [
            [
              "type",
              "==",
              "ipmask"
            ],
            "&&",
            [
              "subnet",
              "<=",
              [
                "3.14.142.0",
                "255.255.255.0"
              ]
            ]
          ],
          "loadsub": 0,
          "url": "/pm/config/adom/DEMO/obj/firewall/address"
        }
      ],
      "session": "BEzK9BQ9ZEMoDQVxCstqIxMWKmCA+Ewi6olABeRf+XbFm9kICX5nXGVwFyDvfg/4SKmT5DzuSS1hEmckePhYiYl5BsZ31EDm",
      "verbose": 1
    }
    

    RESPONSE:

    {
      "id": 1,
      "result": [
        {
          "data": [
            {
              "name": "host_010",
              "subnet": [
                "3.14.142.63",
                "255.255.255.255"
              ]
            }
          ],
          "status": {
            "code": 0,
            "message": "OK"
          },
          "url": "/pm/config/adom/DEMO/obj/firewall/address"
        }
      ]
    }
    
  • To retrieve firewall address strictly matching a specic IP address

    We can use the == comparison operator.

    In the below example, we want all firewall addresses with an exact match for IP address 3.14.142.63/32:

    REQUEST:

    {
      "id": 1,
      "jsonrpc": "1.0",
      "method": "get",
      "params": [
        {
          "fields": [
            "name",
            "subnet"
          ],
          "filter": [
            [
              "type",
              "==",
              "ipmask"
            ],
            "&&",
            [
              "subnet",
              "==",
              [
                "3.14.142.63",
                "255.255.255.255"
              ]
            ]
          ],
          "loadsub": 0,
          "url": "/pm/config/adom/DEMO/obj/firewall/address"
        }
      ],
      "session": "7StdWXSR+aCBi96k+XIsX7QiYJllIiObsp6MouYr5T9Zov+R5sNnTHs8jbO3mgOO0O77Di4wsdKaPSk1SgKh1uTnLUf7ba8j",
      "verbose": 1
    }
    

    RESPONSE:

    {
      "id": 1,
      "result": [
        {
          "data": [
            {
              "name": "host_010",
              "subnet": [
                "3.14.142.63",
                "255.255.255.255"
              ]
            }
          ],
          "status": {
            "code": 0,
            "message": "OK"
          },
          "url": "/pm/config/adom/DEMO/obj/firewall/address"
        }
      ]
    }
    
  • To retrieve all firewall addresses containing a specific IP address

    We can use the >= comparison operator.

    In the below example, we want all firewall addresses containing IP 10.1.0.111/32.

    REQUEST:

    {
      "id": 1,
      "jsonrpc": "1.0",
      "method": "get",
      "params": [
        {
          "fields": [
            "name",
            "subnet"
          ],
          "filter": [
            [
              "type",
              "==",
              "ipmask"
            ],
            "&&",
            [
              "subnet",
              ">=",
              [
                "10.1.0.111",
                "255.255.255.255"
              ]
            ]
          ],
          "loadsub": 0,
          "url": "/pm/config/adom/DEMO/obj/firewall/address"
        }
      ],
      "session": "HjL4TOtmT+DejM8SEeBYwGZGNM6LhetafH9cgsLyf7ikeODmr2YlyipIW6b0VuaxqxEhaox9oXha0huWjA4Y7HHYMFnwpSWV",
      "verbose": 1
    }
    

    RESPONSE:

    {
      "id": 1,
      "result": [
        {
          "data": [
            {
              "name": "FABRIC_DEVICE",
              "subnet": [
                "0.0.0.0",
                "0.0.0.0"
              ]
            },
            {
              "name": "FIREWALL_AUTH_PORTAL_ADDRESS",
              "subnet": [
                "0.0.0.0",
                "0.0.0.0"
              ]
            },
            {
              "name": "all",
              "subnet": [
                "0.0.0.0",
                "0.0.0.0"
              ]
            }
          ],
          "status": {
            "code": 0,
            "message": "OK"
          },
          "url": "/pm/config/adom/DEMO/obj/firewall/address"
        }
      ]
    }
    

3.12.2.3. How to get the Last Modified timestamp?#

The following example will get the Last Modified timestamp (i.e., _modified timestamp) for the firewall address groups declared in the dc_amer ADOM:

{
  "id": 3,
  "method": "get",
  "params": [
    {
      "fields": [
        "name",
        "_modified timestamp"
      ],
      "option": [
        "extra info",
        "no loadsub"
      ],
      "url": "/pm/config/adom/dc_amer/obj/firewall/addrgrp"
    }
  ],
  "session": "PT2or1RfAXowIdjpnhHiEx4W6p12Hx3AkWE5RK9noPTLN5gKy79kywOSYEL5P5vjAc2Ymvt7Zo9OoXV8TndYfQ=="
}
{
  "id": 3,
  "result": [
    {
      "data": [
        {
          "_created timestamp": 1681399819,
          "_last-modified-by": "admin",
          "_modified timestamp": 1681399819,
          "name": "G Suite",
          "obj ver": 1,
          "oid": 3699
        },
        {
          "_created timestamp": 1681399819,
          "_last-modified-by": "admin",
          "_modified timestamp": 1681399819,
          "name": "Microsoft Office 365",
          "obj ver": 1,
          "oid": 3700
        },
        {
          "_created timestamp": 1681408275,
          "_last-modified-by": "admin",
          "_modified timestamp": 1681813548,
          "name": "host_grp_001",
          "obj ver": 3,
          "oid": 5170
        },
        {
          "_created timestamp": 1681408290,
          "_last-modified-by": "admin",
          "_modified timestamp": 1681813548,
          "name": "host_grp_002",
          "obj ver": 4,
          "oid": 5171
        },
        {
          "_created timestamp": 1684190778,
          "_last-modified-by": "admin",
          "_modified timestamp": 1684190778,
          "name": "grp_001",
          "obj ver": 1,
          "oid": 5235
        }
      ],
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/dc_amer/obj/firewall/addrgrp"
    }
  ]
}

3.12.2.4. How to filter on the Last Modified timestamp?#

Idea is to retrieve the list of objects more recent that a specific timestamp.

Caught in #0539624.

{
  "id": 1,
  "method": "get",
  "params": [
    {
      "url": "pm/config/adom/FortiOS-54/obj/firewall/address",
      "option": [
        "get used",
        "get flags",
        "get devobj mapping",
        "get meta",
        "extra info",
        "no loadsub"
      ],
      "filter": [
        "_modified timestamp",
        ">=",
        1549412522
      ]
    }
  ]
            }

Note

The option of interest is extra info.

3.12.2.5. The like operator#

What if goal is to retrieve all firewall addresses whose name start with host_?

{
  "id": 3,
  "method": "get",
  "params": [
    {
      "fields": [
        "name",
        "subnet"
      ],
      "filter": [
        "name",
        "like",
        "host_%"
      ],
      "loadsub": 0,
      "url": "/pm/config/adom/demo/obj/firewall/address"
    }
  ],
  "session": "Wvq6WltRC50vmipqJhAacFrS0RAr/sxQGdrr3NaT2SbAdcz8XzyPbZTd98ewBhiFtMmWLDLkUrSQWCVGhqzvZA==",
  "verbose": 1
}

3.12.2.6. How to delete multiple objects?#

The filter operator can also be very useful to delete multiple objects with a single FortiManager JSON RPC API request.

For instance to delete all firewall addresses starting with host_:

REQUEST:

{
  "id": 1,
  "create task": {
    "adom": "dc_amer"
  },
  "method": "delete",
  "params": [
    {
      "filter": [
          "name",
          "like",
          "host_%"
      ],
      "url": "/pm/config/adom/dc_amer/obj/firewall/address"
    }
  ],
  "session": "{{session}}"
}

Note

  • We’re using the create task to get a sucessful response!

  • In this case, we will just receive a task ID and we will have to review the task output.

  • The filter operator is for all name starting with host_.

RESPONSE:

{
  "id": 1,
  "result": [
    {
      "data": {
        "task": 7
      },
      "status": {
        "code": 0,
        "message": "OK"
      }
    }
  ]
}

Task failed!

Message (captured from the FortiManager GUI) is:

The command is invalid for selected url

OK…

In fact, an yes message is really not meaningful, we need to confirm such dangerous delete form.

We could place the wrong filter and delete a lot of objects!

Let’s retry by confirming the operation:

REQUEST:

{
  "id": 1,
  "create task": {
    "adom": "dc_amer"
  },
  "method": "delete",
  "params": [
    {
      "confirm": 1,
      "filter": [
          "name",
          "like",
          "host_%"
      ],
      "url": "/pm/config/adom/dc_amer/obj/firewall/address"
    }
  ],
  "session": "{{session}}"
}

Note

  • To confirm, you just need to use the confirm attribute.

But… Wait. The task failed again!

used

Of course, our objects are used in some firewall policies.

Let’s force the delete operation!

REQUEST:

{
  "id": 1,
  "create task": {
    "adom": "dc_amer"
  },
  "method": "delete",
  "params": [
    {
      "confirm": 1,
      "option": "force",
      "filter": [
          "name",
          "like",
          "host_%"
      ],
      "url": "/pm/config/adom/dc_amer/obj/firewall/address"
    }
  ],
  "session": "{{session}}"
}

Note

  • To force the requested operation, you have to use the option attribute set with the force keyword.

This time the task is succeeded.

Warning

The operation is succeeded even if you have the following FortiManager CLI setting disabled:

config system admin setting
    set objects-force-deletion disable
end

As a last word, on this particular exemple, to delete just the list of objects (and not more matching the previous used filter value) you could have used the following filter:

"filter": [
  "name",
  "in",
  "host_001",
  "host_002",
  "host_003",
]

3.12.3. Used/Unused objects#

Note

This section will take the firewall address table as example, but you can apply it to all other tables.

3.12.3.1. How to know whether a specific object is used?#

We can use the option get used and observe the returned obj flags.

Our firewall address foo_host_001 is member of a firewall address group. It is only used in this firewall address group.

If we get it with the option get used, we can see a returned obj flags:

REQUEST:

{
  "id": 1,
  "jsonrpc": "1.0",
  "method": "get",
  "params": [
    {
      "fields": [
        "name",
        "obj flags"
      ],
      "loadsub": 0,
      "option": [
        "get used"
      ],
      "url": "/pm/config/adom/production_001/obj/firewall/address/foo_host_001"
    }
  ],
  "session": "oc+DBEboJovBLDkoYqyFkB3dnhoazTP1fbVTRIi1XbVHmVTvuL2A+lUxuYnhjk3L9Sdd74g/SqaOGFQO1saVB2aouTDXWgQg",
  "verbose": 1
}

RESPONSE:

{
  "id": 1,
  "result": [
    {
      "data": {
        "name": "foo_host_001",
        "obj flags": 1
      },
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/production_001/obj/firewall/address/foo_host_001"
    }
  ]
}

When obj flags is equal to 1 it means the object is used.

If we remove firewall address foo_host_001 from the group it was belonging to, the same request now gives:

RESPONSE:

{
  "id": 1,
  "result": [
    {
      "data": {
        "name": "foo_host_001"
      },
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/production_001/obj/firewall/address/foo_host_001"
    }
  ]
}

The obj flags is no longer returned meaning the object isn’t used.

3.12.3.2. How to get the list of used objects?#

You can get the list of used objects by getting the table only using the get used option as seen in section How to know whether a specific object is used?

For instance:

REQUEST:

{
  "id": 3,
  "method": "get",
  "params": [
    {
      "fields": [
        "name"
      ],
      "option": [
        "no loadsub",
        "get used"
      ],
      "url": "/pm/config/adom/production_001/obj/firewall/address"
    }
  ],
  "session": "Shc2xxYYd6Q0apcJAYewlcFxv/pgyCg/ADzB0hC187N1i70lzP9v2808/D2F89JhRFKPbxVAv0XiiK8SUAjrPQ==",
  "verbose": 1
}

RESPONSE:

{
  "id": 3,
  "result": [
    {
      "data": [
        {
          "name": "FABRIC_DEVICE",
          "oid": 2644
        },
        {
          "name": "FIREWALL_AUTH_PORTAL_ADDRESS",
          "oid": 2643
        },
        {
          "name": "RFC1918-10",
          "obj flags": 1,
          "oid": 2646
        },
        {
          "name": "RFC1918-172",
          "obj flags": 1,
          "oid": 2647
        },
        "...": "...",
        {
          "name": "metadata-server",
          "oid": 2645
        },
        {
          "name": "none",
          "oid": 2634
        },
        {
          "name": "wildcard.dropbox.com",
          "oid": 2640
        },
        {
          "name": "wildcard.google.com",
          "obj flags": 1,
          "oid": 2639
        }
      ],
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/knock_45329/obj/firewall/address"
    }
  ]
}

However, as you can see, FortiManager is still returning all firewall addresses!

You have to filter by yourself and isolate the returned objects which are using the obj flags.

You can try to add a filter block:

"filter": [
  "obj flags",
  "==",
  1
]

but it won’t work.

Fortunately, we can ask FortiManager to only return used objects using the following request:

REQUEST:

{
  "id": 3,
  "method": "get",
  "params": [
    {
      "fields": [
        "name"
      ],
      "filter": [
        [
          "object used",
          "==",
          1
        ],
        "&&",
        [
          "name",
          "like",
          "host_%"
        ]
      ],
      "option": [
        "no loadsub",
        "get used"
      ],
      "url": "/pm/config/adom/knock_45329/obj/firewall/address"
    }
  ],
  "session": "tdGYyiDdeDNhiaGmXCJShCAnWS+N5AIeWcb1bMtccP3xNmG6bGONVWUZkU5j+fpTAR48BlvGDfrebJdAcZGQBg==",
  "verbose": 1
}

RESPONSE:

{
  "id": 3,
  "result": [
    {
      "data": [
        {
          "name": "host_001",
          "obj flags": 1,
          "oid": 4156
        },
        {
          "name": "host_002",
          "obj flags": 1,
          "oid": 4157
        },
        {
          "name": "host_003",
          "obj flags": 1,
          "oid": 4158
        },
        "...": "...",
        {
          "name": "host_198",
          "obj flags": 1,
          "oid": 4353
        },
        {
          "name": "host_199",
          "obj flags": 1,
          "oid": 4354
        },
        {
          "name": "host_200",
          "obj flags": 1,
          "oid": 4355
        }
      ],
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/knock_45329/obj/firewall/address"
    }
  ]
}

Note

  • You can keep using the get used option just to confirm that all returned objects have the flag obj flags set to 1.

3.12.3.3. How to get unused objects?#

To get all unused firewall addresses from ADOM demo and matching a specific name:

REQUEST:

{
  "id": 3,
  "method": "get",
  "params": [
    {
      "fields": [
        "name"
      ],
      "filter": [
        [
          "object used",
          "==",
          0
        ],
        "&&",
        [
          "name",
          "like",
          "host_%"
        ]
      ],
      "option": [
        "search all adoms",
        "no loadsub"
      ],
      "url": "/pm/config/adom/knock_45329/obj/firewall/address"
    }
  ],
  "session": "Iu1Msbu+H9FQO/IjfnpRMI96BfCoASYDwzizRfmx6Th6xcMWmCuERL4KYmej7vTRfR58KTYKNqRMbxa25l0vMg==",
  "verbose": 1
}

RESPONSE:

{
  "id": 3,
  "result": [
    {
      "data": [
        {
          "name": "host_201",
          "oid": 4489
        },
        {
          "name": "host_300",
          "oid": 4481
        }
      ],
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/knock_45329/obj/firewall/address"
    }
  ]
}

3.12.4. Where Used#

3.12.4.1. How to where used from the global adom?#

  1. First of all, you have to allow FortiManager to search in all ADOMs:

    config system global
    set search-all-adoms enable
    end
    
  2. Then it’s a three steps process:

    1. Start a where used request

      In this example, we have the global object g_host_001 in the Global ADOM. We want to see where this object is used in all ADOMs.

      {
        "id": 1,
        "method": "exec",
        "params": [
          {
            "data": {
              "mkey": "g_host_001",
              "obj": "global/obj/firewall/address"
            },
            "url": "/cache/search/where/used/start"
          }
        ],
        "session": "{{session}}"
      }
      
      {
        "id": 1,
        "result": [
          {
            "data": {
              "token": "K11EnEPIkRUx23ws7sbm6A=="
            },
            "status": {
              "code": 0,
              "message": "OK"
            },
            "url": "/cache/search/where/used/start"
          }
        ]
      }
      

      Note

      • FortiManager returns the token attribute.

      • Its value will allow you to follow the progress of the task, then to get the final result

    2. Wait for the where used task to complete

      {
        "id": 1,
        "method": "exec",
        "params": [
          {
            "token": "K11EnEPIkRUx23ws7sbm6A==",
            "url": "cache/search/where/used/get/summary"
          }
        ],
        "session": "{{session}}"
      }
      
      {
        "id": 1,
        "result": [
          {
            "data": {
              "percent": 100
            },
            "status": {
              "code": 0,
              "message": "OK"
            },
            "url": "cache/search/where/used/get/summary"
          }
        ]
      }
      

      Note

      • The percent attribute is 100 meaning the task is 100% complete.

      • Should your value different than 100, just keep looping with same request till it returns 100

    3. We can now get the final result

      {
        "id": 1,
        "method": "exec",
        "params": [
          {
            "token": "K11EnEPIkRUx23ws7sbm6A==",
            "url": "/cache/search/where/used/get/detail"
          }
        ],
        "session": "{{session}}"
      }
      
      {
        "id": 1,
        "result": [
          {
            "data": {
              "percent": 100,
              "total_num": 1,
              "where_used": [
                {
                  "data": [
                    {
                      "attr": "dstaddr",
                      "category": 181,
                      "mapping_name": "firewall policy",
                      "mattr": "policyid",
                      "mkey": "4",
                      "pkg": {
                        "name": "pp.device1",
                        "oid": 4710
                      }
                    }
                  ],
                  "root": {
                    "name": "DEMO_014",
                    "oid": 22039
                  }
                }
              ]
            },
            "status": {
              "code": 0,
              "message": "OK"
            },
            "url": "/cache/search/where/used/get/detail"
          }
        ]
      }
      

      Note

      This output shows that:

      • Object g_host_001 is used as a destination in policy package pp.device1

      • The firewall policy referencing object g_host_001 is having the policyid 4

      • The policy package pp.device1 is in ADOM DEMO_014

3.12.4.2. How to where used from within a normal ADOM?#

Follow the same three steps process as the one describe in How to where used from the global adom?

You just need to replace the obj attribute’s value with something like:

adom/<adom>/obj/firewall/address

For instance, if you want to where used the host_001 firewall address from within the dc_emea ADOM, your step 1 request will be:

{
  "id": 1,
  "method": "exec",
  "params": [
    {
      "data": {
        "mkey": "host_001",
        "obj": "adom/dc_emea/obj/firewall/address"
      },
      "url": "/cache/search/where/used/start"
    }
  ],
  "session": "{{session}}"
}

3.12.5. Find duplicates objects#

To get duplicates firewall addresses:

REQUEST:

{
  "id": 1,
  "jsonrpc": "1.0",
  "method": "get",
  "params": [
    {
      "fields": [
        "name",
        "type",
        "subnet",
        "duplicate enntries"
      ],
      "load assigned": 0,
      "loadsub": 0,
      "option": [
        "find duplicates"
      ],
      "url": "/pm/config/adom/demo_002/obj/firewall/address"
    }
  ],
  "session": "V3pHwSOgmHZEQoqJ4pVHJFQSCIiaXm0cOjvXp40JN1ps2FQWNwqMNz0jATnrQxGr2K78L6+mY9Os8WRVBRCxKw==",
  "verbose": 1
}

RESPONSE:

{
  "id": 1,
  "result": [
    {
      "data": [
        {
          "duplicate entries": [
            "login.microsoft.com",
            "login.microsoftonline.com",
            "login.windows.net",
            "wildcard.dropbox.com",
            "wildcard.google.com"
          ],
          "name": "gmail.com",
          "subnet": [
            "0.0.0.0",
            "0.0.0.0"
          ],
          "type": "fqdn"
        },
        {
          "duplicate entries": [
            "FIREWALL_AUTH_PORTAL_ADDRESS",
            "all"
          ],
          "name": "FABRIC_DEVICE",
          "subnet": [
            "0.0.0.0",
            "0.0.0.0"
          ],
          "type": "ipmask"
        },
        {
          "duplicate entries": [
            "host_001_002"
          ],
          "name": "host_001_001",
          "subnet": [
            "10.0.0.1",
            "255.255.255.255"
          ],
          "type": "ipmask"
        }
      ],
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/demo_002/obj/firewall/address"
    }
  ]
}

FortiManager is using the fields attribute to format the response logic. For instance, if we remove the type criteria we will obtain this output:

REQUEST:

{
  "id": 1,
  "jsonrpc": "1.0",
  "method": "get",
  "params": [
    {
      "fields": [
        "name",
        "subnet"
      ],
      "load assigned": 0,
      "loadsub": 0,
      "option": [
        "find duplicates"
      ],
      "url": "/pm/config/adom/demo_002/obj/firewall/address"
    }
  ],
  "session": "qpzdhu+2yDsbeuGJQB/OUGjnmIa+/35YCJrXTudpteCy2XnTgHPEeFZaYHs4sHq1yFQohl7NkpfVjkW7H1dUxF5/i1JnAyE+",
  "verbose": 1
}

RESPONSE:

{
  "id": 1,
  "result": [
    {
      "data": [
        {
          "duplicate entries": [
            "FCTEMS_ALL_FORTICLOUD_SERVERS",
            "FIREWALL_AUTH_PORTAL_ADDRESS",
            "SSLVPN_TUNNEL_ADDR1",
            "all",
            "gmail.com",
            "login.microsoft.com",
            "login.microsoftonline.com",
            "login.windows.net",
            "wildcard.dropbox.com",
            "wildcard.google.com"
          ],
          "name": "FABRIC_DEVICE",
          "subnet": [
            "0.0.0.0",
            "0.0.0.0"
          ]
        },
        {
          "duplicate entries": [
            "host_001_002"
          ],
          "name": "host_001_001",
          "subnet": [
            "10.0.0.1",
            "255.255.255.255"
          ]
        }
      ],
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/demo_002/obj/firewall/address"
    }
  ]
}

Observe where are now listed the firewall addresses FIREWALL_AUTH_PORTAL_ADDRESS and all.

The find duplicates option is working with other objects, like address groups, IPv6 firewall addresses, VIP, etc. You just have to replace the url parameter with the proper path.

3.12.6. Merge objects#

3.12.6.1. How to merge firewall addresses?#

We want to merge firewall address host_001_001 and host_001_002. Destination firewall address name has to be one of them; we cannot merge for instance to firewall address name host_001_merged.

In below example, we will merge both firewall address in host_001_001:

REQUEST:

{
  "id": 1,
  "jsonrpc": "1.0",
  "method": "set",
  "params": [
    {
      "merge": [
        "host_001_001",
        "host_001_002"
      ],
      "url": "/pm/config/adom/demo_002/obj/firewall/address/host_001_001"
    }
  ],
  "session": "1PIOQRlz0dKA/xk8nUY1dsmOuiI7rHcjaAyiTjbaSzJVnpa8smZ8VSUAsWn7NWW/ZZWusUbbrNfte0RgNHdInGwTCiQICw3Y",
  "verbose": 1
}

RESPONSE:

{
  "id": 1,
  "result": [
    {
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/demo_002/obj/firewall/address/host_001_001"
    }
  ]
}

Note that the above merge operation is also:

  • Replacing firewall address host_001_002 with firewall address host_001_001 everywhere it was used (in firewall policy, in firewall address group, etc.)

  • Deleting firewall address host_001_002

The merge operation is working with other objects, like address groups, IPv6 firewall addresses, VIP, etc. You just have to replace the url parameter with the proper path.

3.12.7. Find and Replace#

In the below example, we want to replace the antivirus profile av-profile-001 used by some of our firewall policies, with antivirus profile av-profile-002.

First you need to where used the antivirus profile av-profile-001 object:

  • As you know the where used is a three steps process:

    • Step #1: We Need To Start A New Where Used Task

      REQUEST:

      {
        "id": 1,
        "method": "exec",
        "params": [
          {
            "data": {
              "flags": [
               "direct used"
              ],
              "mkey": "av-profile-001",
              "obj": "adom/DEMO/obj/antivirus/profile"
            },
            "url": "cache/search/where/used/start"
          }
        ],
        "session": 20456
      }
      

      RESPONSE:

      {
        "id": 1,
        "result": [
          {
            "data": {
              "token": "ng9jCDhg9qZVmUt4oaYPZw=="
            },
            "status": {
              "code": 0,
              "message": "OK"
            },
            "url": "cache/search/where/used/start"
          }
        ]
      }
      
    • Step #2: with the returned token, we need to wait for the task to be completed:

      REQUEST:

      {
        "id": 1,
        "method": "exec",
        "params": [
          {
            "token": "ng9jCDhg9qZVmUt4oaYPZw==",
            "url": "cache/search/where/used/get/summary"
          }
        ],
        "session": 20456
      }
      

      RESPONSE:

      {
        "id": 1,
        "result": [
          {
            "data": {
              "percent": 100
            },
            "status": {
              "code": 0,
              "message": "OK"
            },
            "url": "cache/search/where/used/get/summary"
          }
        ]
      }
      

      If the percent value isn’t equal to 100, just retry till it is 100.

    • Step #3: we can collect the where used result:

      REQUEST:

      {
        "id": 1,
        "method": "exec",
        "params": [
          {
            "token": "ng9jCDhg9qZVmUt4oaYPZw==",
            "url": "cache/search/where/used/get/detail"
          }
        ],
        "session": 20456
      }
      

      RESPONSE:

      {
        "id": 1,
        "result": [
          {
            "data": {
              "percent": 100,
              "total_num": 2,
              "where_used": [
                {
                  "data": [
                    {
                      "attr": "av-profile",
                      "category": 181,
                      "mapping_name": "firewall policy",
                      "mattr": "policyid",
                      "mkey": "1",
                      "pkg": {
                        "name": "default",
                        "oid": 4685
                      }
                    },
                    {
                      "attr": "av-profile",
                      "category": 181,
                      "mapping_name": "firewall policy",
                      "mattr": "policyid",
                      "mkey": "2",
                      "pkg": {
                        "name": "default",
                        "oid": 4685
                      }
                    }
                  ],
                  "root": {
                    "name": "DEMO",
                    "oid": 136
                                                  }
                }
              ]
            },
            "status": {
              "code": 0,
              "message": "OK"
            },
            "url": "cache/search/where/used/get/detail"
          }
        ]
      }
      

      From the above output, we can see that our antivirus profile av-profile-001 is used by two firewall policies (id 1 and 2 respectively) in policy package default from ADOM DEMO.

  • We can now proceed with the replace operation

    • To replace av-profile-001 with av-profile-002 for policy #1

      REQUEST:

      {
        "id": 1,
        "method": "update",
        "params": [
          {
            "url": "pm/config/adom/DEMO/pkg/default/firewall/policy/1",
            "used objs": {
              "from": "obj/antivirus/profile/av-profile-001",
              "to": [
                "av-profile-002"
              ]
            }
          }
        ],
        "session": 20456
      }
      

      RESPONSE:

      TBD

3.12.7.1. How to find and replace objects in firewall policy?#

Caught in #0636807.

REQUEST:

{
  "method": "update",
  "params": [
{
      "target start": 2,
      "url": "pm/config/adom/BusySYSLabFG/pkg/BUSYSYSLABFG_Monitoring/firewall/policy/3",
      "used objs": {
                "from": "obj/firewall/address/192.168.215.157-VCenter",
        "to": [
                    "10.1.0.0/16-IT_BUSY"
                  ]
      }
    }
  ],
  "session": 4131
}

3.12.8. Partial installation#

Caught in #0225600.

This is the template to install any objects:

{
  "id": 1,
  "method": "exec",
  "params": [
    {
      "data": {
        "adom": "{{adom}}>",
        "scope": [
          {
            "name": "{{device}}",
            "vdom": "{{vdom}}"
          },
          {"...", "..."}
        ],
        "target": [
          "{{target}}"
        ]
      },
      "url": "/securityconsole/install/objects"
    }
  ],
  "session": "{{session}}",
}

where:

  • scope could be omitted, in that case FortiManager will manage to find the devices/vdoms which are using the target object

  • target is the target object to be install

    You declare a target using the usual format.

    For instance:

    # For any objects
    /pm/config/adom/<adom>/obj/<fortios cli>
    
    # For a firewall policyid
    /pm/config/adom/<adom>/pkg/<pkg>/firewall/policy/<policyid>
    
    etc.
    

More information about the partial install mechanism are given in section Partial Install

3.12.8.1. How to partial install an IPS profile?#

3.12.8.1.1. Using the Legacy Partial Install API#

See Legacy Partial Install API for more details about the Legacy Partial Install API.

The following example shows how to partial install the ips_sensor_001 IPS profile from the demo ADOM against the dev_001 and dev_002 managed device and their respective root VDOM:

{
  "id": 1,
  "method": "exec",
  "params": [
    {
      "data": {
        "adom": "demo",
        "scope": [
          {
            "name": "dev_001",
            "vdom": "root"
          },
          {
            "name": "dev_002",
            "vdom": "root"
          }
        ],
        "target": [
          "/pm/config/adom/demo/obj/ips/sensor/ips_sensor_001"
        ]
      },
      "url": "/securityconsole/install/objects"
    }
  ],
  "session": "{{session}}"
}
{
  "id": 1,
  "result": [
    {
      "data": {
        "task": 441
      },
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/securityconsole/install/objects"
    }
  ]
}
3.12.8.1.2. Using the New Partial Install API#

See New Partial Install API for more details about the New Partial Install API.

The following example shows how to partial install the ips_sensor_001 IPS profile from the demo ADOM against the dev_001 and dev_002 managed device and their respective root VDOM:

{
  "id": 3,
  "method": "exec",
  "params": [
    {
      "data": {
        "adom": "demo",
        "flags": 0,
        "objects": [
          [
            "update",
            "obj/ips/sensor/ips_sensor_001",
            "",
            ""
          ]
        ],
        "scope": [
          {
            "name": "dev_001",
            "vdom": "root"
          },
          {
            "name": "dev_002",
            "vdom": "root"
          }
        ]
      },
      "url": "/securityconsole/install/objects/v2"
    }
  ],
  "session": "{{session}}"
}
{
  "id": 3,
  "result": [
    {
      "data": {
        "task": 948
      },
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/securityconsole/install/objects/v2"
    }
  ]
}

Note

  • It is important to wait for the end of the returned task ID before closing the API session

  • If you close the API session before, the task will fail

3.12.9. How to check for a duplicate object name?#

Caught in #893698

To check whether an object name is already used, you can use the option duplicate check:

"option": [
    "duplicate check"
]

For instance, to check whether a firewall address with name host_001 already exists in ADOM dc_amiens:

{
  "method": "add",
  "id": 1,
  "session": "{{session}}",
  "params": [
    {
      "data": {

      },
      "url": "/pm/config/adom/dc_amiens/obj/firewall/address/host_001",
      "option": ["duplicate check"]
    }
  ]
}

Note

  • The method attribute is add

{
  "result": [
    {
      "data": "firewall address",
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/dc_amiens/obj/firewall/address/host_001"
    }
  ],
  "id": 1
}

The data attribute contains the object’s category, here firewall address.

{
  "result": [
    {
      "data": null,
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/dc_amiens/obj/firewall/address/host_001"
    }
  ],
  "id": 1
}

The data attribute is null.

3.13. Global ADOM#

3.14. Object Revision#

3.14.1. How to add an object with an object revision note?#

Following example applies to firewall address object type.

It is showing how to add a new firewall address with an object revision note:

{
  "id": 3,
  "method": "add",
  "params": [
    {
      "data": {
        "color": 4,
        "name": "host_005",
        "subnet": "10.0.0.5/32"
      },
      "revision note": "Initial Revision",
      "url": "/pm/config/adom/dc_amer/obj/firewall/address"
    }
  ],
  "session": "{{ session }}"
}

3.14.2. How to update an object with an object revision note?#

Following example applies to firewall address object type.

It is showing how to update both an existing firewall address and its associated object revision note:

{
  "id": 3,
  "method": "update",
  "params": [
    {
      "data": {
        "color": 10
      },
      "revision note": "Color changed a second time",
      "url": "/pm/config/adom/dc_amer/obj/firewall/address/host_005"
    }
  ],
  "session": "{{ session }}"
}

3.14.3. How to get the revision notes for a specific object?#

Following example applies to firewall address object type.

It is showing how to get the revision notes for an existing firewall address:

{
  "id": 3,
  "method": "get",
  "params": [
    {
      "url": "/pm/config/adom/dc_amer/_objrev/obj/firewall/address/host_005"
    }
  ],
  "session": "{{ session }}",
  "verbose": 1
}

3.14.4. How to revert to a specific object revision?#

Following example applies to firewall address object type.

It is showing how to revert an existing firewall address to a specific object revision.

In fact, there’s no specific revert operation. FortiManager is using the replace FortiManager JSON RPC API method with datas obtained from the object revision to be reverted with:

{
  "id": 3,
  "method": "replace",
  "params": [
    {
      "data": {
        "color": 4,
        "name": "host_005",
        "subnet": "10.0.0.5/32"
      },
      "revision note": "Reverted from revision 1",
      "url": "/pm/config/adom/dc_amer/obj/firewall/address/host_005"
    }
  ],
  "session": "{{ session }}"
}

3.15. How to copy objects?#

Here the word copy refers to the action of copying an object from ADOM DB to Device DB.

The target object isn’t push down to the managed devices.

A proper install operation should be triggered.

The FortiManager JSON RPC API endpoint used to trigger this copy operation isn’t documented hence we used the output of the following FortiManager debug command compile the information shared in this section:

diagnose debug service main 255

When we issue the following FortiManager CLI command to trigger a copy operation, we’re getting the following output:

# execute fmpolicy copy-adom-object dc_helsinki "firewall address" foo_002 france
Do you want to continue? (y/n)y

Request [/bin/newcli:14057:3]:
{ "client": "\/bin\/newcli:14057", "id": 3, "method": "exec", "params": [{ "data": { "adom": 3273, "category": 140, "override_conflict": 1, "query_only": 0, "scope": [{ "oid": 3569}], "src_list": [{ "oid": 4827}]}, "url": "install\/global"}], "root": "securityconsole", "session": 12207}
Waiting for task 1347...
Task completed

In the following example, we copy the foo_002 firewall address from the dc_helsinki ADOM to the devices belonging to the france device group:

{
  "id": 3,
  "method": "exec",
  "params": [
    {
      "data": {
        "adom": "dc_helsinki",
        "category": 140,
        "override_conflict": 1,
        "query_only": 0,
        "scope": [
          {
            "name": "france"
          }
        ],
        "src_list": [
          {
            "oid": 4827
          }
        ]
      },
      "url": "/securityconsole/install/global"
    }
  ],
  "session": "{{session}}"
}
{
  "id": 3,
  "result": [
    {
      "data": {
        "task": 1350
      },
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/securityconsole/install/global"
    }
  ]
}

FortiManager will return a task ID (task attribute) but won’t run it in the background. We have to wait for the end of the request.

The request is having a lot of numerical information:

  • The category attribute

    • 140 is the category ID for the firewall address table

    • Unfortunately, we cannot use the string "firewall address" as shown below:

      {
        "category": "firewall address"
      }
      

      We have to use an id

      How to get it?

      To get the category ID of the firewall address table:

      {
        "id": 3,
        "method": "get",
        "params": [
          {
            "option": [
              "syntax"
            ],
            "url": "/pm/config/adom/dc_helsinki/obj/firewall/address"
          }
        ],
        "session": "{{session}}"
      }
      

      In the response, you have to get:

      .result[0]["data"]["firewall address"]["category"]
      
  • src_list attribute

    • This list contains the OID of the objects to copy

    • For the 140 category (firewall address) the src_list list contain OID of firewall address objects

    • How to get the OID of a firewall address?

      {
        "id": 3,
        "method": "get",
        "params": [
          {
            "fields": [
              "name"
            ],
            "loadsub": 0,
            "url": "/pm/config/adom/dc_helsinki/obj/firewall/address/foo_002"
          }
        ],
        "session": "7bQB94D0zHu7I9EGtwIbQJEbrcH7qRBI/hwWbqrP/RVUWLd8h1PiFyTD+brojmELiV/rVHcSdYX2CqTAtEcmhg=="
      }
      
      {
        "id": 3,
        "result": [
          {
            "data": {
              "name": "foo_002",
              "oid": 4827
            },
            "status": {
              "code": 0,
              "message": "OK"
            },
            "url": "/pm/config/adom/dc_helsinki/obj/firewall/address/foo_002"
          }
        ]
      }
      

You can use the usual scope:

{
  "scope": [
     {
       "name": "device_group_001",
     },
     {
       "name": "device_group_002",
     },
     {
       "name": "device_001",
       "vdom": "vd_001"
     },
     {
       "name": "device_001",
       "vdom": "vd_002"
     },
     {
        "...": "..."
     }
  ]
}

3.16. Per-device mapping#

This is a mechanism where FortiManager can push the same object to multiple devices, but with different values.

For instance, you could have the net_branch_lan firewall address to represent the internal network of your remote sites and you would like it to be with the 10.0.1.0/24 for site #1, 10.0.2.0/24 for site #2, etc.

The per-device mapping feature isn’t available for all objects.

Note

  • CLI Template could be use to overcome the lack of per-device mapping support.

3.16.1. Per-device mapping for firewall.address#

3.16.1.1. How to get per-device mapping info for a firewall address obejct?#

The following example shows how to get the per-device mapping info for the net_branch_lan firewall address from the demo ADOM:

{
  "id": 3,
  "method": "get",
  "params": [
    {
      "url": "/pm/config/adom/demo/obj/firewall/address/net_branch_lan/dynamic_mapping"
    }
  ],
  "session": "{{session}}",
  "verbose": 1
}

Note

  • To get the per-device mapping info, you just need to append the dynamic_mapping subtable in the url

{
  "id": 3,
  "result": [
    {
      "data": [
        {
          "_scope": [
            {
              "name": "dev_001",
              "vdom": "root"
            }
          ],
          "allow-routing": "disable",
          "clearpass-spt": "unknown",
          "color": 0,
          "dirty": "dirty",
          "fabric-object": "disable",
          "macaddr": [],
          "node-ip-only": "disable",
          "obj-type": "ip",
          "oid": 5584,
          "route-tag": 0,
          "subnet": [
            "10.0.1.0",
            "255.255.255.0"
          ],
          "type": "ipmask",
          "unset attrs": [
            "associated-interface"
          ],
          "uuid": "6c108da4-d257-51ee-25be-c01339bbfdb8"
        }
      ],
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/demo/obj/firewall/address/net_branch_lan/dynamic_mapping"
    }
  ]
}

Note

  • The net_branch_lan is having a single per-device mapping for the dev_001 device and its root VDOM

  • When FortiManager will push the net_branch_lan against the dev_001.root device, it will use the IP address from the subnet block

  • When FortiManager will push the net_branch_lan against the dev_002.root device, it will use the IP address from the subnet block of the net_branch_lan object itself, because there’s no per-device mapping for this device.

3.16.1.2. How to add a per-device mapping to a firewall address object?#

The following example shows how to add a new per-device mapping entry for the dev_002 device and its root VDOM, for the net_branch_lan firewall address from the demo ADOM:

{
  "id": 3,
  "method": "add",
  "params": [
    {
      "data": {
        "_scope": [
          {
            "name": "dev_002",
            "vdom": "root"
          }
        ],
        "subnet": [
          "10.0.2.0",
          "255.255.255.0"
        ]
      },
      "url": "/pm/config/adom/demo/obj/firewall/address/net_branch_lan/dynamic_mapping"
    }
  ],
  "session": "{{session}}"
}
{
  "id": 3,
  "result": [
    {
      "data": {
        "_scope": [
          {
            "name": "dev_002",
            "vdom": "root"
          }
        ]
      },
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/demo/obj/firewall/address/net_branch_lan/dynamic_mapping"
    }
  ]
}

Note

  • FortiManager confirms the creation of the new per-device mapping entry returning its _scope attribute

You can add multiple per-device mapping entries in a single request.

The following example add per-device mapping entries for the dev_003 and dev_004 devices and their root VDOM:

{
  "id": 3,
  "method": "add",
  "params": [
    {
      "data": [
        {
          "_scope": [
            {
              "name": "dev_003",
              "vdom": "root"
            }
          ],
          "subnet": [
            "10.0.3.0",
            "255.255.255.0"
          ]
        },
        {
          "_scope": [
            {
              "name": "dev_004",
              "vdom": "root"
            }
          ],
          "subnet": [
            "10.0.4.0",
            "255.255.255.0"
          ]
        }
      ],
      "url": "/pm/config/adom/demo/obj/firewall/address/net_branch_lan/dynamic_mapping"
    }
  ],
  "session": "{{session}}",
}
{
  "id": 3,
  "result": [
    {
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/demo/obj/firewall/address/net_branch_lan/dynamic_mapping"
    }
  ]
}

Note

  • For multiple per-device mapping entries, FortiManager confirms their creation with a generic OK response

3.16.1.3. How to delete a per-device mapping from a firewall address object?#

The following example shows how to delete the per-device mapping entry for the dev_004 device and its root VDOM, for the net_branch_lan firewall address from the demo ADOM:

{
  "id": 3,
  "method": "delete",
  "params": [
    {
      "url": "/pm/config/adom/demo/obj/firewall/address/net_branch_lan/dynamic_mapping/dev_004/root"
    }
  ],
  "session": "{{session}}"
}
{
  "id": 3,
  "result": [
    {
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/demo/obj/firewall/address/net_branch_lan/dynamic_mapping/dev_004/root"
    }
  ]
}

You can delete multiple per-device mapping entries in a single request.

The following example delete per-device mapping entries for the dev_003 and dev_002 devices and their root VDOM:

{
  "id": 3,
  "method": "delete",
  "params": [
    {
      "url": "/pm/config/adom/demo/obj/firewall/address/net_branch_lan/dynamic_mapping/dev_003/root"
    },
    {
      "url": "/pm/config/adom/demo/obj/firewall/address/net_branch_lan/dynamic_mapping/dev_002/root"
    }
  ],
  "session": "{{session}}"
}
{
  "id": 3,
  "result": [
    {
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/demo/obj/firewall/address/net_branch_lan/dynamic_mapping/dev_03/root"
    },
    {
      "status": {
        "code": 0,
        "message": "OK"
      },
      "url": "/pm/config/adom/demo/obj/firewall/address/net_branch_lan/dynamic_mapping/dev_002/root"
    }
  ]
}