Closed blkistsg closed 1 year ago
Hi @blkistsg , It seems that I have not been able to reproduce your situation, can you please re-check again?
My validation:
# cat maintst.tf
provider "fortios" {
hostname = "192.168.52.177"
token = "rGqsgj9Qmh3dwfQdc8hd3t3G6xG3N5"
insecure = "true"
}
resource "fortios_vpnipsec_phase1interface" "aws_hq_wan1" {
name = "aws-hq-wan1"
interface = "port2"
ike_version = "2"
peertype = "any"
proposal = "aes256-sha256"
dhgrp = "21"
local_gw = "1.1.1.1"
remote_gw = "2.2.2.2"
psksecret = "XXXsssssssssssXXX"
nattraversal = "forced"
}
resource "fortios_vpnipsec_phase2interface" "aws_hq_wan1" {
name = fortios_vpnipsec_phase1interface.aws_hq_wan1.name
phase1name = fortios_vpnipsec_phase1interface.aws_hq_wan1.name
pfs = "enable"
proposal = "aes256-sha256"
dhgrp = "21"
keylifeseconds = 3600
}
# terraform apply
----
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# fortios_vpnipsec_phase1interface.aws_hq_wan1 will be created
+ resource "fortios_vpnipsec_phase1interface" "aws_hq_wan1" {
+ acct_verify = (known after apply)
+ add_gw_route = (known after apply)
+ add_route = (known after apply)
+ assign_ip = (known after apply)
+ assign_ip_from = (known after apply)
+ authmethod = (known after apply)
+ authmethod_remote = (known after apply)
+ authusr = (known after apply)
+ authusrgrp = (known after apply)
+ auto_discovery_forwarder = (known after apply)
+ auto_discovery_psk = (known after apply)
+ auto_discovery_receiver = (known after apply)
+ auto_discovery_sender = (known after apply)
+ auto_negotiate = (known after apply)
+ cert_id_validation = (known after apply)
+ childless_ike = (known after apply)
+ client_auto_negotiate = (known after apply)
+ client_keep_alive = (known after apply)
+ default_gw = (known after apply)
+ default_gw_priority = (known after apply)
+ dhgrp = "21"
+ digital_signature_auth = (known after apply)
+ distance = (known after apply)
+ dns_mode = (known after apply)
+ domain = (known after apply)
+ dpd = (known after apply)
+ dpd_retrycount = (known after apply)
+ dpd_retryinterval = (known after apply)
+ eap = (known after apply)
+ eap_identity = (known after apply)
+ encap_local_gw4 = (known after apply)
+ encap_local_gw6 = (known after apply)
+ encap_remote_gw4 = (known after apply)
+ encap_remote_gw6 = (known after apply)
+ encapsulation = (known after apply)
+ encapsulation_address = (known after apply)
+ enforce_unique_id = (known after apply)
+ exchange_interface_ip = (known after apply)
+ exchange_ip_addr4 = (known after apply)
+ exchange_ip_addr6 = (known after apply)
+ forticlient_enforcement = (known after apply)
+ fragmentation = (known after apply)
+ fragmentation_mtu = (known after apply)
+ group_authentication = (known after apply)
+ ha_sync_esp_seqno = (known after apply)
+ id = (known after apply)
+ idle_timeout = (known after apply)
+ idle_timeoutinterval = (known after apply)
+ ike_version = "2"
+ include_local_lan = (known after apply)
+ interface = "port2"
+ ip_version = (known after apply)
+ ipv4_dns_server1 = (known after apply)
+ ipv4_dns_server2 = (known after apply)
+ ipv4_dns_server3 = (known after apply)
+ ipv4_end_ip = (known after apply)
+ ipv4_name = (known after apply)
+ ipv4_netmask = (known after apply)
+ ipv4_split_exclude = (known after apply)
+ ipv4_split_include = (known after apply)
+ ipv4_start_ip = (known after apply)
+ ipv4_wins_server1 = (known after apply)
+ ipv4_wins_server2 = (known after apply)
+ ipv6_dns_server1 = (known after apply)
+ ipv6_dns_server2 = (known after apply)
+ ipv6_dns_server3 = (known after apply)
+ ipv6_end_ip = (known after apply)
+ ipv6_name = (known after apply)
+ ipv6_prefix = (known after apply)
+ ipv6_split_exclude = (known after apply)
+ ipv6_split_include = (known after apply)
+ ipv6_start_ip = (known after apply)
+ keepalive = (known after apply)
+ keylife = (known after apply)
+ local_gw = "1.1.1.1"
+ local_gw6 = (known after apply)
+ localid = (known after apply)
+ localid_type = (known after apply)
+ mesh_selector_type = (known after apply)
+ mode = (known after apply)
+ mode_cfg = (known after apply)
+ monitor = (known after apply)
+ monitor_hold_down_delay = (known after apply)
+ monitor_hold_down_time = (known after apply)
+ monitor_hold_down_type = (known after apply)
+ monitor_hold_down_weekday = (known after apply)
+ name = "aws-hq-wan1"
+ nattraversal = "forced"
+ negotiate_timeout = (known after apply)
+ net_device = (known after apply)
+ passive_mode = (known after apply)
+ peer = (known after apply)
+ peergrp = (known after apply)
+ peerid = (known after apply)
+ peertype = "any"
+ ppk = (known after apply)
+ ppk_identity = (known after apply)
+ priority = (known after apply)
+ proposal = "aes256-sha256"
+ psksecret = (sensitive value)
+ reauth = (known after apply)
+ rekey = (known after apply)
+ remote_gw = "2.2.2.2"
+ remote_gw6 = (known after apply)
+ remotegw_ddns = (known after apply)
+ rsa_signature_format = (known after apply)
+ save_password = (known after apply)
+ send_cert_chain = (known after apply)
+ signature_hash_alg = (known after apply)
+ split_include_service = (known after apply)
+ suite_b = (known after apply)
+ tunnel_search = (known after apply)
+ type = (known after apply)
+ unity_support = (known after apply)
+ usrgrp = (known after apply)
+ vni = (known after apply)
+ wizard_type = (known after apply)
+ xauthtype = (known after apply)
}
# fortios_vpnipsec_phase2interface.aws_hq_wan1 will be created
+ resource "fortios_vpnipsec_phase2interface" "aws_hq_wan1" {
+ add_route = (known after apply)
+ auto_discovery_forwarder = (known after apply)
+ auto_discovery_sender = (known after apply)
+ auto_negotiate = (known after apply)
+ dhcp_ipsec = (known after apply)
+ dhgrp = "21"
+ dst_addr_type = (known after apply)
+ dst_end_ip = (known after apply)
+ dst_end_ip6 = (known after apply)
+ dst_name = (known after apply)
+ dst_name6 = (known after apply)
+ dst_port = (known after apply)
+ dst_start_ip = (known after apply)
+ dst_start_ip6 = (known after apply)
+ dst_subnet = (known after apply)
+ dst_subnet6 = (known after apply)
+ encapsulation = (known after apply)
+ id = (known after apply)
+ keepalive = (known after apply)
+ keylife_type = (known after apply)
+ keylifekbs = (known after apply)
+ keylifeseconds = 3600
+ l2tp = (known after apply)
+ name = "aws-hq-wan1"
+ pfs = "enable"
+ phase1name = "aws-hq-wan1"
+ proposal = "aes256-sha256"
+ protocol = (known after apply)
+ replay = (known after apply)
+ route_overlap = (known after apply)
+ single_source = (known after apply)
+ src_addr_type = (known after apply)
+ src_end_ip = (known after apply)
+ src_end_ip6 = (known after apply)
+ src_name = (known after apply)
+ src_name6 = (known after apply)
+ src_port = (known after apply)
+ src_start_ip = (known after apply)
+ src_start_ip6 = (known after apply)
+ src_subnet = (known after apply)
+ src_subnet6 = (known after apply)
}
Plan: 2 to add, 0 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_vpnipsec_phase1interface.aws_hq_wan1: Creating...
fortios_vpnipsec_phase1interface.aws_hq_wan1: Creation complete after 0s [id=aws-hq-wan1]
fortios_vpnipsec_phase2interface.aws_hq_wan1: Creating...
fortios_vpnipsec_phase2interface.aws_hq_wan1: Creation complete after 0s [id=aws-hq-wan1]
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
Then I changed the interface name to 'port3' and executed it again. The result was successful:
root@sv:/work/zamba/03fos-gen/03Terraform/bin# terraform apply
----
fortios_vpnipsec_phase1interface.aws_hq_wan1: Refreshing state... [id=aws-hq-wan1]
fortios_vpnipsec_phase2interface.aws_hq_wan1: Refreshing state... [id=aws-hq-wan1]
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
~ update in-place
Terraform will perform the following actions:
# fortios_vpnipsec_phase1interface.aws_hq_wan1 will be updated in-place
~ resource "fortios_vpnipsec_phase1interface" "aws_hq_wan1" {
acct_verify = "disable"
add_gw_route = "disable"
add_route = "enable"
assign_ip = "enable"
assign_ip_from = "range"
authmethod = "psk"
auto_discovery_forwarder = "disable"
auto_discovery_psk = "disable"
auto_discovery_receiver = "disable"
auto_discovery_sender = "disable"
auto_negotiate = "enable"
cert_id_validation = "enable"
childless_ike = "disable"
client_auto_negotiate = "disable"
client_keep_alive = "disable"
default_gw = "0.0.0.0"
default_gw_priority = 0
dhgrp = "21"
digital_signature_auth = "disable"
distance = 15
dns_mode = "manual"
dpd = "on-demand"
dpd_retrycount = 3
dpd_retryinterval = "20"
eap = "disable"
eap_identity = "use-id-payload"
encap_local_gw4 = "0.0.0.0"
encap_local_gw6 = "::"
encap_remote_gw4 = "0.0.0.0"
encap_remote_gw6 = "::"
encapsulation = "none"
encapsulation_address = "ike"
enforce_unique_id = "disable"
exchange_interface_ip = "disable"
exchange_ip_addr4 = "0.0.0.0"
exchange_ip_addr6 = "::"
forticlient_enforcement = "disable"
fragmentation = "enable"
fragmentation_mtu = 1200
group_authentication = "disable"
ha_sync_esp_seqno = "enable"
id = "aws-hq-wan1"
idle_timeout = "disable"
idle_timeoutinterval = 15
ike_version = "2"
include_local_lan = "disable"
~ interface = "port2" -> "port3"
ip_version = "4"
ipv4_dns_server1 = "0.0.0.0"
ipv4_dns_server2 = "0.0.0.0"
ipv4_dns_server3 = "0.0.0.0"
ipv4_end_ip = "0.0.0.0"
ipv4_netmask = "255.255.255.255"
ipv4_start_ip = "0.0.0.0"
ipv4_wins_server1 = "0.0.0.0"
ipv4_wins_server2 = "0.0.0.0"
ipv6_dns_server1 = "::"
ipv6_dns_server2 = "::"
ipv6_dns_server3 = "::"
ipv6_end_ip = "::"
ipv6_prefix = 128
ipv6_start_ip = "::"
keepalive = 10
keylife = 86400
local_gw = "1.1.1.1"
local_gw6 = "::"
localid_type = "auto"
mesh_selector_type = "disable"
mode = "main"
mode_cfg = "disable"
monitor_hold_down_delay = 0
monitor_hold_down_time = "00:00"
monitor_hold_down_type = "immediate"
monitor_hold_down_weekday = "sunday"
name = "aws-hq-wan1"
nattraversal = "forced"
negotiate_timeout = 30
net_device = "enable"
passive_mode = "disable"
peertype = "any"
ppk = "disable"
priority = 0
proposal = "aes256-sha256"
psksecret = (sensitive value)
reauth = "disable"
rekey = "enable"
remote_gw = "2.2.2.2"
remote_gw6 = "::"
rsa_signature_format = "pkcs1"
save_password = "disable"
send_cert_chain = "enable"
signature_hash_alg = "sha2-512 sha2-384 sha2-256 sha1"
suite_b = "disable"
tunnel_search = "selectors"
type = "static"
unity_support = "enable"
vni = 0
wizard_type = "custom"
xauthtype = "disable"
}
Plan: 0 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_vpnipsec_phase1interface.aws_hq_wan1: Modifying... [id=aws-hq-wan1]
fortios_vpnipsec_phase1interface.aws_hq_wan1: Modifications complete after 0s [id=aws-hq-wan1]
Apply complete! Resources: 0 added, 1 changed, 0 destroyed.
The operation mode of modifying the interface name here is consistent with the operation mode of CLI. By the way, can you please keep the line breaks in the terraform configuration you pasted? I have to reformat the content you pasted to analyze them. Thanks!
@frankshen01
What he's trying to change is the field name
name = "aws-hq-wan1"
Not the interface name field. The name field is used to generate a new interface (if you check at conf sys interface
).
Thanks @mbdraks.
Hi @blkistsg Please do not try to expect the terraform resource to be created by modifying the name field only, you need to modify the name of the resource itself at the same time. This means:
resource "fortios_vpnipsec_phase1interface" "tr1abc" {
name = "abc"
interface = "port2"
ike_version = "2"
peertype = "any"
proposal = "aes256-sha256"
dhgrp = "21"
local_gw = "1.1.1.1"
remote_gw = "2.2.2.2"
psksecret = "XXXsssssssssssXXX"
nattraversal = "forced"
}
If only the name field is modified here, terraform will regard it as modifying the original resource fortios_vpnipsec_phase1interface.tr1abc. The correct approach is to modify the resource name at the same time:
resource "fortios_vpnipsec_phase1interface" "tr1cde" { <==================================
name = "cde" <=========================================
interface = "port2"
ike_version = "2"
peertype = "any"
proposal = "aes256-sha256"
dhgrp = "21"
local_gw = "1.1.1.1"
remote_gw = "2.2.2.2"
psksecret = "XXXsssssssssssXXX"
nattraversal = "forced"
}
At this time terraform thinks that new resources fortios_vpnipsec_phase1interface.tr1cde will be created and the old ones fortios_vpnipsec_phase1interface.tr1abc will be destroyed.
Refer: https://github.com/hashicorp/terraform/issues/10792 , as terraform founder mitchellh and terraform developer apparentlymart described:
mitchellh: Terraform tracks resources by their name. If you change the name, you have created a new resource and deleted the old resource. apparentlymart: One consequence of that is that Terraform can't tell if it's being asked to "create" a resource that already exists...
By the way, for the creation and modification of fortios_vpnipsec_phase1interface/fortios_vpnipsec_phase2interface/fortios_system_interface, the creation and modification can theoretically be realized in the following way:
variable "address_object_subnets" {
type = list
default = ["sda1"]
}
resource "fortios_vpnipsec_phase1interface" "tr1" {
for_each = toset(var.address_object_subnets)
name = each.key
interface = "port2"
ike_version = "2"
peertype = "any"
proposal = "aes256-sha256"
dhgrp = "21"
local_gw = "1.1.1.1"
remote_gw = "2.2.2.2"
psksecret = "XXXsssssssssssXXX"
nattraversal = "forced"
}
resource "fortios_vpnipsec_phase2interface" "tr2" {
for_each = toset(var.address_object_subnets)
name = fortios_vpnipsec_phase1interface.tr1[each.key].name
phase1name = fortios_vpnipsec_phase1interface.tr1[each.key].name
pfs = "enable"
proposal = "aes256-sha256"
dhgrp = "21"
keylifeseconds = 3600
}
resource "fortios_system_interface" "tr2" {
for_each = toset(var.address_object_subnets)
vdom = "root"
name = fortios_vpnipsec_phase2interface.tr2[each.key].name
ip = "10.10.10.2 255.255.255.255"
remote_ip = "172.22.1.30 255.255.255.255"
interface = "port2"
allowaccess = "ping"
tcp_mss = "1350"
autogenerated = "auto"
}
But if the resource fortios_vpnipsec_phase1interface is unchanged except for the resource name and the name field, the above method is not feasible, since terraform still has the following problems, as described in https://discuss.hashicorp.com/t/destroy-before-create/3980/3. which means the new fortios_vpnipsec_phase1interface may be created before the old fortios_vpnipsec_phase1interface is destroyed, if the fortios_vpnipsec_phase1interface is unchanged except for the resource name and the name field, the FGT creation will fail. In view of this situation, execute terraform destroy first, and then execute terraform apply is a better way. Thanks!
@frankshen01 - This is not the behavior of other providers, for instance the AWS provider (probably the most mature). My understanding is that the provider should codify which settings are able to be modified directly vs. which need to force a complete destroy/create cycle of the resource. If I'm not mistaken, it is done by marking the schema elements for the resource which cannot be modified directly with the ForceNew
behavior.
Here is the documentation in HashiCorp docs: https://www.terraform.io/docs/extend/schemas/schema-behaviors.html#forcenew
Hi @StratusChris, you are totally right, your suggestion is wonderful. Thanks for the guidance. The bug will be fixed, it will be included in the next release (within a week). Thank you!
Thanks so much @frankshen01 ! I suspect this same fix is needed for every resource where the name field is used as the object id in the FortiGate (almost all resources seem to fall under this since ids are not usually generated by the FortiGate).
We really appreciate all the work you're doing on this provider, you're making really fast progress and it's very meaningful for us!
Hi @StratusChris, thanks for your kind words. The feature has been supported and released, please see the latest version(v1.6.15): https://registry.terraform.io/providers/fortinetdev/fortios/latest. Let me know if you need anything else. Thanks again!
I will go ahead to close this case, if you still have questions, feel free to reopen it or another case.
FortiOS 6.4
My guess is that it is because it is trying to change it instead of delete and re-add it. I don't think you can just edit the name on the VpnIpsecPhase1Interface