Fortinet Document Library

Version:


Table of Contents

More Links

Download Terraform
Download FortiOS provider
FortiOS provider parameters for Terraform

Cookbook

6.2.0
Download PDF
Copy Link

Terraform: Fortinet as a provider

Fortinet's Terraform support with new provider modules provides customers with more ways to efficiently deploy, manage, and automate security across even the most complex multicloud environments. It enables the ability to accelerate experimentation, eliminate misconfiguration errors, simplify policy rollout and change management, and ultimately provide organizations with more confidence to implement new applications regardless of the complexity of the infrastructures on which they are being deployed.

Terraform's automation can include any FortiOS-related operations on physical and virtual FortiGates. When hosted an automation master, you can use Terraform to automate various IT infrastructure needs, thereby eliminating threats introduced by IT staff manually misconfiguring devices. For example, if Fortinet is releasing a new FortiOS version, your organization may require you to test any new functionality to determine how it may impact the environment before globally deploying the new version. In this case, the ability to rapidly stand up environments and test these functions prior to production environment integration offers an extremely resource-efficient and fault-tolerant approach.

This configuration requires the following:

  • FortiOS 6.0 or 6.2
  • FortiOS Provider: This example uses terraform-provider-fortios 1.0.0.
  • Terraform: This example uses Terraform 0.11.14.
  • REST API administrator created on the FortiGate with the API key
To configure FortiGate with Terraform Provider module support:
  1. Place the terraform-provider-fortios file in a directory. Create a new file with the .tf extension:

    root@mail:/home/terraform# ls

    terraform-provider-fortios_v1.0.0_x4 test.tf

  2. Create a configuration file that contains the FortiGate's connection information and some configuration changes. This example updates the DNS address (resource "fortios_system_setting_dns" "test1" {) and creates a new static route (resource "fortios_networking_route_static" "test1" {). The FortiGate's IP address is 10.6.30.5, and 17bGctGrdzz5hkzf6z1zr4g8zt63ck is the API user token:

    # Configure the FortiOS Provider

    provider "fortios" {

    hostname = "10.6.30.5" <--- FGT IP

    token = "17bGctGrdzz5hkzf6z1zr4g8zt63ck"

    }

    resource "fortios_system_setting_dns" "test1" {

    primary = "208.91.112.53"

    secondary = "208.91.112.22"

    }

    resource "fortios_networking_route_static" "test1" {

    dst = "110.2.2.122/32"

    gateway = "2.2.2.2"

    blackhole = "disable"

    distance = "22"

    weight = "3"

    priority = "3"

    device = "port2"

    comment = "Terraform test"

    }

  3. Enter terraform init to initialize the working directory. It reads the provider if the name follows the convention terraform-provider-[name]:

    root@mail:/home/terraform# terraform init

    Initializing the backend...

    Terraform has been successfully initialized!

    You may now begin working with Terraform. Try running "terraform plan" to see

    any changes that are required for your infrastructure. All Terraform commands

    should now work.

    If you ever set or change modules or backend configuration for Terraform,

    rerun this command to reinitialize your working directory. If you forget, other

    commands will detect it and remind you to do so if necessary.

  4. Enter terraform plan to parse the .tf configuration file and also read from the FortiGate configuration and see what Terraform changes in the end. This example creates a static route and updates the DNS address. You can see that Terraform reads the current DNS addresses from the FortiGate and lists them as well:

    root@mail:/home/terraform# terraform plan

    Refreshing Terraform state in-memory prior to plan...

    The refreshed state will be used to calculate this plan, but will not be

    persisted to local or remote state storage.

    fortios_networking_route_static.test1: Refreshing state... (ID: 2)

    fortios_system_setting_dns.test1: Refreshing state... (ID: 208.91.112.53)

    ------------------------------------------------------------------------

    An execution plan has been generated and is shown below.

    Resource actions are indicated with the following symbols:

    + create

    ~ update in-place

    Terraform will perform the following actions:

    + fortios_networking_route_static.test1

    id: <computed>

    blackhole: "disable"

    comment: "Terraform test"

    device: "port2"

    distance: "22"

    dst: "110.2.2.122/32"

    gateway: "2.2.2.2"

    priority: "3"

    weight: "3"

    ~ fortios_system_setting_dns.test1

    primary: "208.91.112.53" => "172.16.95.16"

    secondary: "208.91.112.22" => "8.8.8.8"

    Plan: 1 to add, 1 to change, 0 to destroy.

    ------------------------------------------------------------------------

    Note: You didn't specify an "-out" parameter to save this plan, so Terraform

    can't guarantee that exactly these actions will be performed if

    "terraform apply" is subsequently run.

  5. Enter terraform apply to continue with the configuration:

    root@mail:/home/terraform# terraform apply

    fortios_system_setting_dns.test1: Refreshing state... (ID: 208.91.112.53)

    fortios_networking_route_static.test1: Refreshing state... (ID: 2)

    An execution plan has been generated and is shown below.

    Resource actions are indicated with the following symbols:

    + create

    ~ update in-place

    Terraform will perform the following actions:

    + fortios_networking_route_static.test1

    id: <computed>

    blackhole: "disable"

    comment: "Terraform test"

    device: "port2"

    distance: "22"

    dst: "110.2.2.122/32"

    gateway: "2.2.2.2"

    priority: "3"

    weight: "3"

    ~ fortios_system_setting_dns.test1

    primary: "208.91.112.53" => "172.16.95.16"

    secondary: "208.91.112.22" => "8.8.8.8"

    Plan: 1 to add, 1 to change, 0 to destroy.

    Do you want to perform these actions?

    Terraform will perform the actions described above.

    Only 'yes' will be accepted to approve.

    Enter a value: yes

    fortios_networking_route_static.test1: Creating...

    blackhole: "" => "disable"

    comment: "" => "Terraform test"

    device: "" => "port2"

    distance: "" => "22"

    dst: "" => "110.2.2.122/32"

    gateway: "" => "2.2.2.2"

    priority: "" => "3"

    weight: "" => "3"

    fortios_system_setting_dns.test1: Modifying... (ID: 208.91.112.53)

    primary: "208.91.112.53" => "172.16.95.16"

    secondary: "208.91.112.22" => "8.8.8.8"

    fortios_networking_route_static.test1: Creation complete after 0s (ID: 2)

    fortios_system_setting_dns.test1: Modifications complete after 0s (ID: 172.16.95.16)

    Apply complete! Resources: 1 added, 1 changed, 0 destroyed.

  6. The FortiGate is now configured according to the configuration file. If you want to change or delete something in the future, you can edit the configuration file, then apply it again. In supported cases, it deletes, adds, or updates new entries as configured. In this example, for instance, you can remove the static route and revert the DNS address to its original configuration by changing the .tf file:

    # Configure the FortiOS Provider

    provider "fortios" {

    hostname = "10.6.30.5"

    token = "17bGctGrdzz5hkzf6z1zr4g8zt63ck"

    }

    resource "fortios_system_setting_dns" "test1" {

    primary = "208.91.112.53"

    secondary = "208.91.112.22"

    }

    #resource "fortios_networking_route_static" "test1" {

    # dst = "110.2.2.122/32"

    # gateway = "2.2.2.2"

    # blackhole = "disable"

    # distance = "22"

    # weight = "3"

    # priority = "3"

    # device = "port2"

    # comment = "Terraform test"

    #}

  7. Entering terraform apply deletes the static route that is commented out in the configuration .tf file and reverts the DNS address to the old address:

    root@mail:/home/terraform# terraform apply

    fortios_system_setting_dns.test1: Refreshing state... (ID: 172.16.95.16)

    fortios_networking_route_static.test1: Refreshing state... (ID: 2)

    An execution plan has been generated and is shown below.

    Resource actions are indicated with the following symbols:

    ~ update in-place

    - destroy

    Terraform will perform the following actions:

    - fortios_networking_route_static.test1

    ~ fortios_system_setting_dns.test1

    primary: "172.16.95.16" => "208.91.112.53"

    secondary: "8.8.8.8" => "208.91.112.22"

    Plan: 0 to add, 1 to change, 1 to destroy.

    Do you want to perform these actions?

    Terraform will perform the actions described above.

    Only 'yes' will be accepted to approve.

    Enter a value: yes

    fortios_networking_route_static.test1: Destroying... (ID: 2)

    fortios_system_setting_dns.test1: Modifying... (ID: 172.16.95.16)

    primary: "172.16.95.16" => "208.91.112.53"

    secondary: "8.8.8.8" => "208.91.112.22"

    fortios_networking_route_static.test1: Destruction complete after 0s

    fortios_system_setting_dns.test1: Modifications complete after 0s (ID: 208.91.112.53)

    Apply complete! Resources: 0 added, 1 changed, 1 destroyed.

  8. Enter httpsd debug (diagnose debug enable, diagnose debug application httpsd -1) to begin troubleshooting why a configuration was not accepted:

    [httpsd 333 - 1560376452 info] ap_invoke_handler[569] -- new request (handler='api_cmdb_v2-handler', uri='/api/v2/cmdb/router/static/2', method='GET')

    [httpsd 23616 - 1560376452 info] handle_cli_req_v2_vdom[2034] -- new CMDB API request (vdom='root',user='test')

    [httpsd 333 - 1560376452 info] ap_invoke_handler[573] -- User-Agent: Go-http-client/1.1

    [httpsd 23616 - 1560376452 info] api_cmdb_request_init_by_path[1438] -- new CMDB query (path='system',name='dns')

    [httpsd 333 - 1560376452 info] ap_invoke_handler[576] -- Source: 10.6.30.55:49666 Destination: 10.6.30.5:443

    [httpsd 333 - 1560376452 info] api_cmdb_v2_handler[2132] -- received api_cmdb_v2_request from '10.6.30.55'

    [httpsd 23616 - 1560376452 info] api_cmdb_select_etag[2146] -- ETag check for system.dns

    [httpsd 23616 - 1560376452 info] api_return_cmdb_revision[837] -- ETag check for system.dns

    [httpsd 23616 - 1560376452 info] api_add_etag[918] -- no If-None-Match header

    [httpsd 333 - 1560376452 warning] api_access_check_for_api_key[965] -- API Key request authorized for test from 10.6.30.55.

    [httpsd 23616 - 1560376452 info] api_return_cmdb_revision[837] -- ETag check for system.dns

    [httpsd 333 - 1560376452 info] api_store_parameter[239] -- add API parameter 'access_token' (type=string)

    [httpsd 333 - 1560376452 info] handle_cli_req_v2_vdom[2034] -- new CMDB API request (vdom='root',user='test')

    [httpsd 333 - 1560376452 info] api_cmdb_request_init_by_path[1438] -- new CMDB query (path='router',name='static')

    [httpsd 333 - 1560376452 info] api_cmdb_request_init_by_path[1467] -- querying CMDB entry (mkey='2')

    [httpsd 333 - 1560376452 info] api_cmdb_select_etag[2146] -- ETag check for router.static

    [httpsd 333 - 1560376452 info] api_return_cmdb_revision[837] -- ETag check for router.static

    [httpsd 333 - 1560376452 info] api_add_etag[918] -- no If-None-Match header

    [httpsd 333 - 1560376452 info] api_cmdb_v2_object_select[843] -- filter by master key (seq-num)

    [httpsd 23616 - 1560376452 info] ap_invoke_handler[592] -- request completed (handler='api_cmdb_v2-handler' result==0)

More Links

Terraform: Fortinet as a provider

Fortinet's Terraform support with new provider modules provides customers with more ways to efficiently deploy, manage, and automate security across even the most complex multicloud environments. It enables the ability to accelerate experimentation, eliminate misconfiguration errors, simplify policy rollout and change management, and ultimately provide organizations with more confidence to implement new applications regardless of the complexity of the infrastructures on which they are being deployed.

Terraform's automation can include any FortiOS-related operations on physical and virtual FortiGates. When hosted an automation master, you can use Terraform to automate various IT infrastructure needs, thereby eliminating threats introduced by IT staff manually misconfiguring devices. For example, if Fortinet is releasing a new FortiOS version, your organization may require you to test any new functionality to determine how it may impact the environment before globally deploying the new version. In this case, the ability to rapidly stand up environments and test these functions prior to production environment integration offers an extremely resource-efficient and fault-tolerant approach.

This configuration requires the following:

  • FortiOS 6.0 or 6.2
  • FortiOS Provider: This example uses terraform-provider-fortios 1.0.0.
  • Terraform: This example uses Terraform 0.11.14.
  • REST API administrator created on the FortiGate with the API key
To configure FortiGate with Terraform Provider module support:
  1. Place the terraform-provider-fortios file in a directory. Create a new file with the .tf extension:

    root@mail:/home/terraform# ls

    terraform-provider-fortios_v1.0.0_x4 test.tf

  2. Create a configuration file that contains the FortiGate's connection information and some configuration changes. This example updates the DNS address (resource "fortios_system_setting_dns" "test1" {) and creates a new static route (resource "fortios_networking_route_static" "test1" {). The FortiGate's IP address is 10.6.30.5, and 17bGctGrdzz5hkzf6z1zr4g8zt63ck is the API user token:

    # Configure the FortiOS Provider

    provider "fortios" {

    hostname = "10.6.30.5" <--- FGT IP

    token = "17bGctGrdzz5hkzf6z1zr4g8zt63ck"

    }

    resource "fortios_system_setting_dns" "test1" {

    primary = "208.91.112.53"

    secondary = "208.91.112.22"

    }

    resource "fortios_networking_route_static" "test1" {

    dst = "110.2.2.122/32"

    gateway = "2.2.2.2"

    blackhole = "disable"

    distance = "22"

    weight = "3"

    priority = "3"

    device = "port2"

    comment = "Terraform test"

    }

  3. Enter terraform init to initialize the working directory. It reads the provider if the name follows the convention terraform-provider-[name]:

    root@mail:/home/terraform# terraform init

    Initializing the backend...

    Terraform has been successfully initialized!

    You may now begin working with Terraform. Try running "terraform plan" to see

    any changes that are required for your infrastructure. All Terraform commands

    should now work.

    If you ever set or change modules or backend configuration for Terraform,

    rerun this command to reinitialize your working directory. If you forget, other

    commands will detect it and remind you to do so if necessary.

  4. Enter terraform plan to parse the .tf configuration file and also read from the FortiGate configuration and see what Terraform changes in the end. This example creates a static route and updates the DNS address. You can see that Terraform reads the current DNS addresses from the FortiGate and lists them as well:

    root@mail:/home/terraform# terraform plan

    Refreshing Terraform state in-memory prior to plan...

    The refreshed state will be used to calculate this plan, but will not be

    persisted to local or remote state storage.

    fortios_networking_route_static.test1: Refreshing state... (ID: 2)

    fortios_system_setting_dns.test1: Refreshing state... (ID: 208.91.112.53)

    ------------------------------------------------------------------------

    An execution plan has been generated and is shown below.

    Resource actions are indicated with the following symbols:

    + create

    ~ update in-place

    Terraform will perform the following actions:

    + fortios_networking_route_static.test1

    id: <computed>

    blackhole: "disable"

    comment: "Terraform test"

    device: "port2"

    distance: "22"

    dst: "110.2.2.122/32"

    gateway: "2.2.2.2"

    priority: "3"

    weight: "3"

    ~ fortios_system_setting_dns.test1

    primary: "208.91.112.53" => "172.16.95.16"

    secondary: "208.91.112.22" => "8.8.8.8"

    Plan: 1 to add, 1 to change, 0 to destroy.

    ------------------------------------------------------------------------

    Note: You didn't specify an "-out" parameter to save this plan, so Terraform

    can't guarantee that exactly these actions will be performed if

    "terraform apply" is subsequently run.

  5. Enter terraform apply to continue with the configuration:

    root@mail:/home/terraform# terraform apply

    fortios_system_setting_dns.test1: Refreshing state... (ID: 208.91.112.53)

    fortios_networking_route_static.test1: Refreshing state... (ID: 2)

    An execution plan has been generated and is shown below.

    Resource actions are indicated with the following symbols:

    + create

    ~ update in-place

    Terraform will perform the following actions:

    + fortios_networking_route_static.test1

    id: <computed>

    blackhole: "disable"

    comment: "Terraform test"

    device: "port2"

    distance: "22"

    dst: "110.2.2.122/32"

    gateway: "2.2.2.2"

    priority: "3"

    weight: "3"

    ~ fortios_system_setting_dns.test1

    primary: "208.91.112.53" => "172.16.95.16"

    secondary: "208.91.112.22" => "8.8.8.8"

    Plan: 1 to add, 1 to change, 0 to destroy.

    Do you want to perform these actions?

    Terraform will perform the actions described above.

    Only 'yes' will be accepted to approve.

    Enter a value: yes

    fortios_networking_route_static.test1: Creating...

    blackhole: "" => "disable"

    comment: "" => "Terraform test"

    device: "" => "port2"

    distance: "" => "22"

    dst: "" => "110.2.2.122/32"

    gateway: "" => "2.2.2.2"

    priority: "" => "3"

    weight: "" => "3"

    fortios_system_setting_dns.test1: Modifying... (ID: 208.91.112.53)

    primary: "208.91.112.53" => "172.16.95.16"

    secondary: "208.91.112.22" => "8.8.8.8"

    fortios_networking_route_static.test1: Creation complete after 0s (ID: 2)

    fortios_system_setting_dns.test1: Modifications complete after 0s (ID: 172.16.95.16)

    Apply complete! Resources: 1 added, 1 changed, 0 destroyed.

  6. The FortiGate is now configured according to the configuration file. If you want to change or delete something in the future, you can edit the configuration file, then apply it again. In supported cases, it deletes, adds, or updates new entries as configured. In this example, for instance, you can remove the static route and revert the DNS address to its original configuration by changing the .tf file:

    # Configure the FortiOS Provider

    provider "fortios" {

    hostname = "10.6.30.5"

    token = "17bGctGrdzz5hkzf6z1zr4g8zt63ck"

    }

    resource "fortios_system_setting_dns" "test1" {

    primary = "208.91.112.53"

    secondary = "208.91.112.22"

    }

    #resource "fortios_networking_route_static" "test1" {

    # dst = "110.2.2.122/32"

    # gateway = "2.2.2.2"

    # blackhole = "disable"

    # distance = "22"

    # weight = "3"

    # priority = "3"

    # device = "port2"

    # comment = "Terraform test"

    #}

  7. Entering terraform apply deletes the static route that is commented out in the configuration .tf file and reverts the DNS address to the old address:

    root@mail:/home/terraform# terraform apply

    fortios_system_setting_dns.test1: Refreshing state... (ID: 172.16.95.16)

    fortios_networking_route_static.test1: Refreshing state... (ID: 2)

    An execution plan has been generated and is shown below.

    Resource actions are indicated with the following symbols:

    ~ update in-place

    - destroy

    Terraform will perform the following actions:

    - fortios_networking_route_static.test1

    ~ fortios_system_setting_dns.test1

    primary: "172.16.95.16" => "208.91.112.53"

    secondary: "8.8.8.8" => "208.91.112.22"

    Plan: 0 to add, 1 to change, 1 to destroy.

    Do you want to perform these actions?

    Terraform will perform the actions described above.

    Only 'yes' will be accepted to approve.

    Enter a value: yes

    fortios_networking_route_static.test1: Destroying... (ID: 2)

    fortios_system_setting_dns.test1: Modifying... (ID: 172.16.95.16)

    primary: "172.16.95.16" => "208.91.112.53"

    secondary: "8.8.8.8" => "208.91.112.22"

    fortios_networking_route_static.test1: Destruction complete after 0s

    fortios_system_setting_dns.test1: Modifications complete after 0s (ID: 208.91.112.53)

    Apply complete! Resources: 0 added, 1 changed, 1 destroyed.

  8. Enter httpsd debug (diagnose debug enable, diagnose debug application httpsd -1) to begin troubleshooting why a configuration was not accepted:

    [httpsd 333 - 1560376452 info] ap_invoke_handler[569] -- new request (handler='api_cmdb_v2-handler', uri='/api/v2/cmdb/router/static/2', method='GET')

    [httpsd 23616 - 1560376452 info] handle_cli_req_v2_vdom[2034] -- new CMDB API request (vdom='root',user='test')

    [httpsd 333 - 1560376452 info] ap_invoke_handler[573] -- User-Agent: Go-http-client/1.1

    [httpsd 23616 - 1560376452 info] api_cmdb_request_init_by_path[1438] -- new CMDB query (path='system',name='dns')

    [httpsd 333 - 1560376452 info] ap_invoke_handler[576] -- Source: 10.6.30.55:49666 Destination: 10.6.30.5:443

    [httpsd 333 - 1560376452 info] api_cmdb_v2_handler[2132] -- received api_cmdb_v2_request from '10.6.30.55'

    [httpsd 23616 - 1560376452 info] api_cmdb_select_etag[2146] -- ETag check for system.dns

    [httpsd 23616 - 1560376452 info] api_return_cmdb_revision[837] -- ETag check for system.dns

    [httpsd 23616 - 1560376452 info] api_add_etag[918] -- no If-None-Match header

    [httpsd 333 - 1560376452 warning] api_access_check_for_api_key[965] -- API Key request authorized for test from 10.6.30.55.

    [httpsd 23616 - 1560376452 info] api_return_cmdb_revision[837] -- ETag check for system.dns

    [httpsd 333 - 1560376452 info] api_store_parameter[239] -- add API parameter 'access_token' (type=string)

    [httpsd 333 - 1560376452 info] handle_cli_req_v2_vdom[2034] -- new CMDB API request (vdom='root',user='test')

    [httpsd 333 - 1560376452 info] api_cmdb_request_init_by_path[1438] -- new CMDB query (path='router',name='static')

    [httpsd 333 - 1560376452 info] api_cmdb_request_init_by_path[1467] -- querying CMDB entry (mkey='2')

    [httpsd 333 - 1560376452 info] api_cmdb_select_etag[2146] -- ETag check for router.static

    [httpsd 333 - 1560376452 info] api_return_cmdb_revision[837] -- ETag check for router.static

    [httpsd 333 - 1560376452 info] api_add_etag[918] -- no If-None-Match header

    [httpsd 333 - 1560376452 info] api_cmdb_v2_object_select[843] -- filter by master key (seq-num)

    [httpsd 23616 - 1560376452 info] ap_invoke_handler[592] -- request completed (handler='api_cmdb_v2-handler' result==0)