fortinetdev / terraform-provider-fortios

Terraform Fortios provider
https://www.terraform.io/docs/providers/fortios/
Mozilla Public License 2.0
68 stars 50 forks source link

fortios_firewall_policy vs fortios_firewall_security_policy #137

Closed rbcollins123 closed 1 year ago

rbcollins123 commented 3 years ago

I see in the docs that fortios_firewall_security_policy is marked to be deprecated with the direction to use fortios_firewall_policy instead, but it's not clear why?

When we use fortios_firewall_policy to create the same rule in use via fortios_firewall_security_policy, it appears as an SSL Inspection & Authentication rule in the GUI instead of appearing under the Security Policies portion of the UI, so it doesn't seem like it's a functionally equivalent replacement for fortios_firewall_security_policy being deprecated? Or is there some mode-of-use for fortinet_firewall_policy that allows it to edit both resource types (config firewall policy and config firewall security-policy)?

The tests in this case were using NGFW policy-based mode

frankshen01 commented 3 years ago

Hi @rbcollins123 Thanks for raising this!

_>> I see in the docs that fortios_firewall_security_policy is marked to be deprecated with the direction to use fortios_firewallpolicy instead, but it's not clear why? A: Since the underlying SDK was refactored to support multiple versions of FortiOS and also provides the ability to be more conducive to large-scale expansion, so the terraform's calling method、data structure and scalability have also undergone tremendous changes. The scalability of the new version of resources has been greatly enhanced. From a user perspective, the old version is a subset of the new version. In order not to affect the original users, we did not make drastic changes to the old version, and we still keep the old version. But the new version has far more features than the old version, so we recommend using the new version resources. For a new user, it is strongly recommended to ignore the old version and use the new version.

_>> When we use fortios_firewall_policy to create the same rule in use via fortios_firewall_security_policy, it appears as an SSL Inspection & Authentication rule in the GUI instead of appearing under the Security Policies portion of the UI, so it doesn't seem like it's a functionally equivalent replacement for fortios_firewall_security_policy being deprecated? Or is there some mode-of-use for fortinet_firewallpolicy that allows it to edit both resource types (config firewall policy and config firewall security-policy)? A: Could you provide us with the TF configuration of the new and old resources, the FortiGate firmware version(GUI: Dashboard->Status->System Information->Fireware or CLI: get system status->Version) and Terraform version(terraform version) ? We will analyze the problem you mentioned. Thank you!

rbcollins123 commented 3 years ago

@frankshen01 Thanks for the quick response!

I think the deprecation is fine if you're only trying to support fortios while running in NGFW profile-based mode (the legacy operation method for Fortigate). But I don't see how you can do that and provide support for policy-based mode. When I glanced through the methods being called in the fortios_firewall_policy code I didn't see anywhere it was still allowing support for the configure firewall security-policy section of the config needed in the newer mode.

By running a device in NGFW policy-based mode, I mean:

config system settings
    set ngfw-mode policy-based
end

In this mode the policies created via configure firewall policy (what's being called in the fortios_firewall_policy module) are SSL Inspection & Authentiation policies. Those created via configure firewall security-policy(what's being called via the fortios_firewall_security_policy resource) are Security Policies in the UI.

In the legacy NGFW profile-based mode there is a single UI for policies (vs the 2 mentioned above in policy-based mode) because you're using profiles applied to that single list of policies and in CLI there is no configure firewall security-policy command so deprecation seems a non-issue in that mode.

So I can see how it's viable to deprecate it in profile-based mode, but in policy-based mode you'll still need a way to be able to edit entries under configure firewall security-policy either via 2 resource types or by adding magic to the fortios_firewall_policy resource to allow it to determine when to put the policy under configure firewall policy vs configure firewall security-policies. I'd vote not to make the new resource have magic to determine what rule-types are being created in FortiOS, and instead have the 2 resource types. But, if you wanted to only maintain the one it seems you'd need an attribute on the resource to flag which type of rule you're making when targeting a policy-based mode firewall.

Re: an example resource, I'd have to carve out some time to make 2 new equivalent resources using each type and push to a policy-based unit in the coming days/weeks (can't do it at the moment), but you can make any most-basic rule allowing some traffic from anywhere to anywhere in the fortios_firewall_policymodule and apply it to a firewall in profile-based mode and you'll see it appear in the UI under "Policy & Objects\Firewall Policy" as you would expect, then change the mode on that firewall to policy-based and apply the plan and you'll see it appear under "Policy & Objects\SSL Authentiation & Authentication" (you'd actually want that rule to appear in "Policy & Objects\Security Policy")

Here are the versions we used in our lab when we were testing the other day:

Version: FortiGate-VM64-KVM v6.4.4,build1803,201209 (GA)
Virus-DB: 83.00927(2021-02-10 01:20)
Extended DB: 83.00927(2021-02-10 01:20)
Extreme DB: 1.00000(2018-04-09 18:07)
IPS-DB: 6.00741(2015-12-01 02:30)
IPS-ETDB: 17.00009(2021-02-02 01:12)
APP-DB: 17.00008(2021-01-30 02:16)
INDUSTRIAL-DB: 17.00009(2021-02-02 01:12)
Serial-Number: xxxxxxxxxxx
IPS Malicious URL Database: 2.00915(2021-02-09 06:04)
License Status: Valid
VM Resources: 1 CPU/1 allowed, 2010 MB RAM
Log hard disk: Not available
Hostname: fg-lab
Private Encryption: Disable
Operation Mode: NAT
Current virtual domain: root
Max number of virtual domains: 10
Virtual domains status: 1 in NAT mode, 0 in TP mode
Virtual domain configuration: disable
FIPS-CC mode: disable
Current HA mode: standalone
Branch point: 1803
Release Version Information: GA
FortiOS x86-64: Yes

❯ terraform --version
Terraform v0.14.6
+ provider registry.terraform.io/fortinetdev/fortios v1.9.0
+ provider registry.terraform.io/hashicorp/null v2.1.2
rbcollins123 commented 3 years ago

One additional resource that may explain what I'm referring to above is in the Admin guide where they offer an example of creating a policy when in "NGFW policy-based mode" to allow an application to flow, it demonstrates building the 2 types of policies I was referring to above. You can see it HERE

To configure policies for Facebook and Gmail access in the CLI:

Configure an SSL Inspection & Authentication policy:

config firewall policy
    edit 1
        set name "Policy-1"
        set srcintf "port18"
        set dstintf "port17"
        set srcaddr "all"
        set dstaddr "all"
        set service "ALL"
        set ssl-ssh-profile "new-deep-inspection"
        set groups "Dev" "HR" "QA" "SYS"
    next
end

Configure security policies:

config firewall security-policy
    edit 2
        set name "allow-QA-Facebook"
        set srcintf "port18"
        set dstintf "port17"
        set srcaddr "all"
        set dstaddr "all"
        set action accept
        set schedule "always"
        set application 15832
        set groups "Dev" "QA"
    next
    edit 4
        set name "allow-QA-Email"
        set srcintf "port18"
        set dstintf "port17"
        set srcaddr "all"
        set dstaddr "all"
        set action accept
        set schedule "always"
        set url-category 23
        set groups "QA"
    next
end
rbcollins123 commented 3 years ago

Spent some time digging into the Go behind these 2 resource types and I think I see the confusion now. I assumed that fortios_firewall_policy was working against the /api/v2/cmdb/firewall/policy REST endpoint and that fortios_firewall_security_policy was working against the /api/v2/cmdb/firewall/security-policy REST endpoint because of the naming conventions used (these are the 2 REST cmdb routes we'd need to do a NGFW policy-based rule-sets). That's actually not true in the underlying Go SDK, so both end up hitting the same REST /api/v2/cmdb/firewall/policy endpoint (which is fine in NGFW profile-based mode). I actually don't see any support in the Go SDK for the /api/v2/cmdb/firewall/security-policy REST calls based on a quick grep so I'm not sure how TF can manage a Fortigate running in NGFW policy-based mode until it's added to both the SDK and the provider?

frankshen01 commented 3 years ago

@rbcollins123 , thank you for such a detailed and wonderful analysis. You can analyze the reasons clearly in such a short period of time, which is really admirable! There are some historical reasons that need to be introduced for you. All the resources under FortiGate OldVersion were implemented in the first version we launched in 2019. Some fields such as object and security have been added to the resource name to distinguish them, In fact, later, it turned out that these were unnecessary. With the increase in demand, the design and functions of the first version became less and less able to meet the needs of the situation. Later, a second version appeared, which includes most of the FortiOS resources outside the OldVersion directory. At this time, it led to fortios_firewall_security_policy refers to the same API entry as fortios_firewall_policy. In order to prevent confusion to users and not affect existing customers of the first version, we tried to remind users by renaming the directory to OldVersion and adding red warnings, hoping to play the role of not wasting users’ time. But I am sorry that this still caused confusion, very sorry for that. Frankly speaking, when I first read your question, I thought about it for a long time and didn't understand it. I think it must be because I didn't think about it clearly. Later I realized that it was because of this. Regarding the resource corresponding to the config firewall security policy, we will launch this feature in the next major release, estimated in mid-April. If you need it urgently, you can use generic resource instead, one thing to note is that generic does not have the state management function, or contact the SE who serves you to ask the product department to improve the priority of the new feature. If you require any further information, feel free to contact me. Thank you!

yatanasov commented 3 years ago

Hello :) Very insightful information in this issue ! May I use it to ask a question ( a bit of a stretch) - is there any automated way (script or tool) for transforming existing fortios_firewall_security_policy to fortios_firewall_policy ? Imagine a codebase with large number of policies - it would take a lot of refactoring, so I was wondering if there's a way to make things easier :))

frankshen01 commented 3 years ago

Hi @yatanasov Thanks for the feedback! If your configuration is not dynamic, as far as I can think of now, maybe you can try the following steps:

_1. Get the policy id list first with fortios_firewall_security_policy datasource, for example:_

data "fortios_firewall_policylist" sample3 {
  # filter = "schedule==always,schedule==once"
}

output sample3_output {
  value = data.fortios_firewall_policylist.sample3.policyidlist
}

After terraform apply, it will output a result similar to the following:

Outputs:

sample3_output = [
  1,
  2,
  3,
  4,
  7,
  12,
]

2. Then we can write a python(or other language you like) program to do the following:

_2.1 Generate multiple null fortios_firewall_policy resources with the above id list, and save them into a single tf file, for example:_

resource "fortios_firewall_policy" "trnameid1" {
}

resource "fortios_firewall_policy" "trnameid2" {
}

....
resource "fortios_firewall_policy" "trnameid12" {
}

2.2 Then another code snippet can be used to generate import commands:

export "FORTIOS_IMPORT_TABLE"="true"
terraform import fortios_firewall_policy.trnameid1 1
terraform import fortios_firewall_policy.trnameid2 2
....
terraform import fortios_firewall_policy.trnameid12 12
unset "FORTIOS_IMPORT_TABLE"

3. When these commands are executed, all those policies are imported to terraform.

_4. Then 'terraform show', all policies resource will be displayed in terraform HCL format, then copy them to your TF file and overwrite those null fortios_firewall_policy resources._

_5. Delete some unnecessary arguments from fortios_firewall_policy resources according your actual needs(The editor's regular expression replacement function can be very useful here). Delete fortios_firewall_security_policy resources from tf files and delete its status from terraform status file (Be careful, please make a full backup before doing so)._

6. Run terraform plan for verification. If there are any inconsistent, go back to 5, until it prompts: No changes. Infrastructure is up-to-date.

Frankly speaking, this is not a novel solution. But I apologize I can only think of so much at present, it can avoid configuration one by one, thus saving some time. I hope the above can provide some help for your. Feel free to contact me if you need any further information. Thank you!

yatanasov commented 3 years ago

Dear @frankshen01 , thank you so much for taking the time to define and share your solution ! I can totally see what you mean and it will be absolutely sufficient for our needs ! I'd like to thank you and your team for your amazing job with the fortios provider !

frankshen01 commented 3 years ago

@yatanasov My pleasure, I’m happy to help! Thanks for your kind words! BTW: I have made a revision to the above answer ~ the filter in the code of step1 should be deleted to get all policies. For more help about Data Source: fortios_firewall_policylist, please refer to, Data Source: fortios_firewall_policylist. Thank you!

frankshen01 commented 3 years ago

Supported and released, please see the latest version(v1.13.0): https://registry.terraform.io/providers/fortinetdev/fortios/latest and https://registry.terraform.io/providers/fortinetdev/fortios/latest/docs/resources/fortios_firewall_securitypolicy for details. Thanks!