1249 lines
57 KiB
Go
1249 lines
57 KiB
Go
package settings
|
|
|
|
import (
|
|
"context"
|
|
ut "github.com/filipowm/terraform-provider-unifi/internal/provider/types"
|
|
"github.com/hashicorp/terraform-plugin-framework-validators/int64validator"
|
|
"github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault"
|
|
"github.com/hashicorp/terraform-plugin-framework/resource/schema/boolplanmodifier"
|
|
"github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier"
|
|
"github.com/hashicorp/terraform-plugin-framework/resource/schema/objectplanmodifier"
|
|
|
|
"github.com/filipowm/go-unifi/unifi"
|
|
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
|
"github.com/filipowm/terraform-provider-unifi/internal/provider/validators"
|
|
"github.com/hashicorp/terraform-plugin-framework-validators/listvalidator"
|
|
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
|
|
"github.com/hashicorp/terraform-plugin-framework/attr"
|
|
"github.com/hashicorp/terraform-plugin-framework/diag"
|
|
"github.com/hashicorp/terraform-plugin-framework/path"
|
|
"github.com/hashicorp/terraform-plugin-framework/resource"
|
|
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
|
|
"github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier"
|
|
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
|
|
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault"
|
|
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
|
|
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
|
|
"github.com/hashicorp/terraform-plugin-framework/types"
|
|
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
|
|
)
|
|
|
|
// GeoIPFilteringModel represents the GeoIP filtering configuration
|
|
type GeoIPFilteringModel struct {
|
|
Mode types.String `tfsdk:"mode"`
|
|
Countries types.List `tfsdk:"countries"`
|
|
TrafficDirection types.String `tfsdk:"traffic_direction"`
|
|
}
|
|
|
|
func (m *GeoIPFilteringModel) AttributeTypes() map[string]attr.Type {
|
|
return map[string]attr.Type{
|
|
"mode": types.StringType,
|
|
"countries": types.ListType{
|
|
ElemType: types.StringType,
|
|
},
|
|
"traffic_direction": types.StringType,
|
|
}
|
|
}
|
|
|
|
// UpnpModel represents the UPNP configuration
|
|
type UpnpModel struct {
|
|
NatPmpEnabled types.Bool `tfsdk:"nat_pmp_enabled"`
|
|
SecureMode types.Bool `tfsdk:"secure_mode"`
|
|
WANInterface types.String `tfsdk:"wan_interface"`
|
|
}
|
|
|
|
func (m *UpnpModel) AttributeTypes() map[string]attr.Type {
|
|
return map[string]attr.Type{
|
|
"nat_pmp_enabled": types.BoolType,
|
|
"secure_mode": types.BoolType,
|
|
"wan_interface": types.StringType,
|
|
}
|
|
}
|
|
|
|
// TCPTimeoutModel represents the TCP timeout configuration
|
|
type TCPTimeoutModel struct {
|
|
CloseTimeout types.Int64 `tfsdk:"close_timeout"`
|
|
CloseWaitTimeout types.Int64 `tfsdk:"close_wait_timeout"`
|
|
EstablishedTimeout types.Int64 `tfsdk:"established_timeout"`
|
|
FinWaitTimeout types.Int64 `tfsdk:"fin_wait_timeout"`
|
|
LastAckTimeout types.Int64 `tfsdk:"last_ack_timeout"`
|
|
SynRecvTimeout types.Int64 `tfsdk:"syn_recv_timeout"`
|
|
SynSentTimeout types.Int64 `tfsdk:"syn_sent_timeout"`
|
|
TimeWaitTimeout types.Int64 `tfsdk:"time_wait_timeout"`
|
|
}
|
|
|
|
func (m *TCPTimeoutModel) AttributeTypes() map[string]attr.Type {
|
|
return map[string]attr.Type{
|
|
"close_timeout": types.Int64Type,
|
|
"close_wait_timeout": types.Int64Type,
|
|
"established_timeout": types.Int64Type,
|
|
"fin_wait_timeout": types.Int64Type,
|
|
"last_ack_timeout": types.Int64Type,
|
|
"syn_recv_timeout": types.Int64Type,
|
|
"syn_sent_timeout": types.Int64Type,
|
|
"time_wait_timeout": types.Int64Type,
|
|
}
|
|
}
|
|
|
|
// DNSVerificationModel represents the DNS Verification configuration
|
|
type DNSVerificationModel struct {
|
|
Domain types.String `tfsdk:"domain"`
|
|
PrimaryDNSServer types.String `tfsdk:"primary_dns_server"`
|
|
SecondaryDNSServer types.String `tfsdk:"secondary_dns_server"`
|
|
SettingPreference types.String `tfsdk:"setting_preference"`
|
|
}
|
|
|
|
func (m *DNSVerificationModel) AttributeTypes() map[string]attr.Type {
|
|
return map[string]attr.Type{
|
|
"domain": types.StringType,
|
|
"primary_dns_server": types.StringType,
|
|
"secondary_dns_server": types.StringType,
|
|
"setting_preference": types.StringType,
|
|
}
|
|
}
|
|
|
|
// DNSVerificationModel represents the DNS Verification configuration
|
|
type DHCPRelayModel struct {
|
|
AgentsPackets types.String `tfsdk:"agents_packets"`
|
|
HopCount types.Int64 `tfsdk:"hop_count"`
|
|
MaxSize types.Int64 `tfsdk:"max_size"`
|
|
Port types.Int64 `tfsdk:"port"`
|
|
}
|
|
|
|
func (m *DHCPRelayModel) AttributeTypes() map[string]attr.Type {
|
|
return map[string]attr.Type{
|
|
"agents_packets": types.StringType,
|
|
"hop_count": types.Int64Type,
|
|
"max_size": types.Int64Type,
|
|
"port": types.Int64Type,
|
|
}
|
|
}
|
|
|
|
// usgModel represents the data model for USG (UniFi Security Gateway) settings.
|
|
// It defines how USG features like mDNS and DHCP relay are configured for a UniFi site.
|
|
type usgModel struct {
|
|
base.Model
|
|
MulticastDnsEnabled types.Bool `tfsdk:"multicast_dns_enabled"`
|
|
|
|
// Geo IP filtering
|
|
GeoIPFilteringEnabled types.Bool `tfsdk:"geo_ip_filtering_enabled"`
|
|
GeoIPFiltering types.Object `tfsdk:"geo_ip_filtering"`
|
|
|
|
// UPNP configuration
|
|
UpnpEnabled types.Bool `tfsdk:"upnp_enabled"`
|
|
Upnp types.Object `tfsdk:"upnp"`
|
|
|
|
// ARP Cache Configuration
|
|
ArpCacheBaseReachable types.Int64 `tfsdk:"arp_cache_base_reachable"`
|
|
ArpCacheTimeout types.String `tfsdk:"arp_cache_timeout"`
|
|
|
|
// DHCP Configuration
|
|
BroadcastPing types.Bool `tfsdk:"broadcast_ping"`
|
|
DhcpdHostfileUpdate types.Bool `tfsdk:"dhcpd_hostfile_update"`
|
|
DhcpdUseDnsmasq types.Bool `tfsdk:"dhcpd_use_dnsmasq"`
|
|
DnsmasqAllServers types.Bool `tfsdk:"dnsmasq_all_servers"`
|
|
DhcpRelayServers types.List `tfsdk:"dhcp_relay_servers"` // TODO deprecated
|
|
DhcpRelay types.Object `tfsdk:"dhcp_relay"`
|
|
|
|
// DNS Verification
|
|
DnsVerification types.Object `tfsdk:"dns_verification"`
|
|
|
|
// Network Tools
|
|
EchoServer types.String `tfsdk:"echo_server"`
|
|
|
|
// Protocol Modules
|
|
FtpModule types.Bool `tfsdk:"ftp_module"`
|
|
GreModule types.Bool `tfsdk:"gre_module"`
|
|
H323Module types.Bool `tfsdk:"h323_module"`
|
|
PptpModule types.Bool `tfsdk:"pptp_module"`
|
|
SipModule types.Bool `tfsdk:"sip_module"`
|
|
TftpModule types.Bool `tfsdk:"tftp_module"`
|
|
|
|
// ICMP Settings
|
|
IcmpTimeout types.Int64 `tfsdk:"icmp_timeout"`
|
|
|
|
// LLDP Settings
|
|
LldpEnableAll types.Bool `tfsdk:"lldp_enable_all"`
|
|
|
|
// MSS Clamp Settings
|
|
MssClamp types.String `tfsdk:"mss_clamp"`
|
|
MssClampMss types.Int64 `tfsdk:"mss_clamp_mss"`
|
|
|
|
// Offload Settings
|
|
OffloadAccounting types.Bool `tfsdk:"offload_accounting"`
|
|
OffloadL2Blocking types.Bool `tfsdk:"offload_l2_blocking"`
|
|
OffloadSch types.Bool `tfsdk:"offload_sch"`
|
|
|
|
// Timeout Settings
|
|
OtherTimeout types.Int64 `tfsdk:"other_timeout"`
|
|
TimeoutSettingPreference types.String `tfsdk:"timeout_setting_preference"`
|
|
|
|
// TCP Settings (nested)
|
|
TcpTimeouts types.Object `tfsdk:"tcp_timeouts"`
|
|
|
|
// Redirects
|
|
ReceiveRedirects types.Bool `tfsdk:"receive_redirects"`
|
|
SendRedirects types.Bool `tfsdk:"send_redirects"`
|
|
|
|
// Security Settings
|
|
SynCookies types.Bool `tfsdk:"syn_cookies"`
|
|
|
|
// UDP Settings
|
|
UdpOtherTimeout types.Int64 `tfsdk:"udp_other_timeout"`
|
|
UdpStreamTimeout types.Int64 `tfsdk:"udp_stream_timeout"`
|
|
|
|
// WAN Settings
|
|
UnbindWanMonitors types.Bool `tfsdk:"unbind_wan_monitors"`
|
|
}
|
|
|
|
func (d *usgModel) AsUnifiModel(ctx context.Context) (interface{}, diag.Diagnostics) {
|
|
diags := diag.Diagnostics{}
|
|
|
|
model := &unifi.SettingUsg{
|
|
ID: d.ID.ValueString(),
|
|
MdnsEnabled: d.MulticastDnsEnabled.ValueBool(),
|
|
}
|
|
|
|
// Extract DHCP relay servers from the list
|
|
var dhcpRelayServers []string
|
|
diags.Append(ut.ListElementsAs(d.DhcpRelayServers, &dhcpRelayServers)...)
|
|
if diags.HasError() {
|
|
return nil, diags
|
|
}
|
|
|
|
// TODO deprecated
|
|
// Assign DHCP relay servers to the model (up to 5)
|
|
// Map each server by index to appropriate field
|
|
serverFields := []struct {
|
|
index int
|
|
fieldPtr *string
|
|
}{
|
|
{0, &model.DHCPRelayServer1},
|
|
{1, &model.DHCPRelayServer2},
|
|
{2, &model.DHCPRelayServer3},
|
|
{3, &model.DHCPRelayServer4},
|
|
{4, &model.DHCPRelayServer5},
|
|
}
|
|
|
|
for _, sf := range serverFields {
|
|
if sf.index < len(dhcpRelayServers) {
|
|
*sf.fieldPtr = dhcpRelayServers[sf.index]
|
|
}
|
|
}
|
|
// TODO end of deprecated
|
|
|
|
// Assign Geo IP filtering attributes
|
|
if ut.IsDefined(d.GeoIPFiltering) {
|
|
var geoIPFiltering *GeoIPFilteringModel
|
|
diags.Append(d.GeoIPFiltering.As(ctx, &geoIPFiltering, basetypes.ObjectAsOptions{})...)
|
|
if diags.HasError() {
|
|
return nil, diags
|
|
}
|
|
|
|
model.GeoIPFilteringBlock = geoIPFiltering.Mode.ValueString()
|
|
model.GeoIPFilteringTrafficDirection = geoIPFiltering.TrafficDirection.ValueString()
|
|
countries, diags := ut.ListElementsToString(ctx, geoIPFiltering.Countries)
|
|
if diags.HasError() {
|
|
return nil, diags
|
|
}
|
|
model.GeoIPFilteringEnabled = true
|
|
model.GeoIPFilteringCountries = countries
|
|
} else {
|
|
model.GeoIPFilteringEnabled = false
|
|
}
|
|
|
|
// Assign UPNP attributes
|
|
if ut.IsDefined(d.Upnp) {
|
|
var upnp *UpnpModel
|
|
diags.Append(d.Upnp.As(ctx, &upnp, basetypes.ObjectAsOptions{})...)
|
|
if diags.HasError() {
|
|
return nil, diags
|
|
}
|
|
|
|
model.UpnpEnabled = true
|
|
model.UpnpNATPmpEnabled = upnp.NatPmpEnabled.ValueBool()
|
|
model.UpnpSecureMode = upnp.SecureMode.ValueBool()
|
|
model.UpnpWANInterface = upnp.WANInterface.ValueString()
|
|
} else {
|
|
model.UpnpEnabled = false
|
|
}
|
|
|
|
if ut.IsDefined(d.TcpTimeouts) {
|
|
var tcpTimeouts *TCPTimeoutModel
|
|
diags.Append(d.TcpTimeouts.As(ctx, &tcpTimeouts, basetypes.ObjectAsOptions{})...)
|
|
if diags.HasError() {
|
|
return nil, diags
|
|
}
|
|
|
|
model.TCPCloseTimeout = int(tcpTimeouts.CloseTimeout.ValueInt64())
|
|
model.TCPCloseWaitTimeout = int(tcpTimeouts.CloseWaitTimeout.ValueInt64())
|
|
model.TCPEstablishedTimeout = int(tcpTimeouts.EstablishedTimeout.ValueInt64())
|
|
model.TCPFinWaitTimeout = int(tcpTimeouts.FinWaitTimeout.ValueInt64())
|
|
model.TCPLastAckTimeout = int(tcpTimeouts.LastAckTimeout.ValueInt64())
|
|
model.TCPSynRecvTimeout = int(tcpTimeouts.SynRecvTimeout.ValueInt64())
|
|
model.TCPSynSentTimeout = int(tcpTimeouts.SynSentTimeout.ValueInt64())
|
|
model.TCPTimeWaitTimeout = int(tcpTimeouts.TimeWaitTimeout.ValueInt64())
|
|
}
|
|
|
|
// Assign DNS Verification attributes
|
|
if ut.IsDefined(d.DnsVerification) {
|
|
var dnsVerification *DNSVerificationModel
|
|
diags.Append(d.DnsVerification.As(ctx, &dnsVerification, basetypes.ObjectAsOptions{})...)
|
|
if diags.HasError() {
|
|
return nil, diags
|
|
}
|
|
|
|
model.DNSVerification = unifi.SettingUsgDNSVerification{
|
|
Domain: dnsVerification.Domain.ValueString(),
|
|
PrimaryDNSServer: dnsVerification.PrimaryDNSServer.ValueString(),
|
|
SecondaryDNSServer: dnsVerification.SecondaryDNSServer.ValueString(),
|
|
SettingPreference: dnsVerification.SettingPreference.ValueString(),
|
|
}
|
|
}
|
|
|
|
if ut.IsDefined(d.DhcpRelay) {
|
|
var dhcpRelay *DHCPRelayModel
|
|
diags.Append(d.DhcpRelay.As(ctx, &dhcpRelay, basetypes.ObjectAsOptions{})...)
|
|
if diags.HasError() {
|
|
return nil, diags
|
|
}
|
|
|
|
model.DHCPRelayAgentsPackets = dhcpRelay.AgentsPackets.ValueString()
|
|
model.DHCPRelayHopCount = int(dhcpRelay.HopCount.ValueInt64())
|
|
model.DHCPRelayMaxSize = int(dhcpRelay.MaxSize.ValueInt64())
|
|
model.DHCPRelayPort = int(dhcpRelay.Port.ValueInt64())
|
|
}
|
|
|
|
model.ArpCacheBaseReachable = int(d.ArpCacheBaseReachable.ValueInt64())
|
|
model.ArpCacheTimeout = d.ArpCacheTimeout.ValueString()
|
|
model.BroadcastPing = d.BroadcastPing.ValueBool()
|
|
model.DHCPDHostfileUpdate = d.DhcpdHostfileUpdate.ValueBool()
|
|
model.DHCPDUseDNSmasq = d.DhcpdUseDnsmasq.ValueBool()
|
|
model.DNSmasqAllServers = d.DnsmasqAllServers.ValueBool()
|
|
model.EchoServer = d.EchoServer.ValueString()
|
|
model.FtpModule = d.FtpModule.ValueBool()
|
|
model.GreModule = d.GreModule.ValueBool()
|
|
model.H323Module = d.H323Module.ValueBool()
|
|
model.PptpModule = d.PptpModule.ValueBool()
|
|
model.SipModule = d.SipModule.ValueBool()
|
|
model.TFTPModule = d.TftpModule.ValueBool()
|
|
model.ICMPTimeout = int(d.IcmpTimeout.ValueInt64())
|
|
model.LldpEnableAll = d.LldpEnableAll.ValueBool()
|
|
model.MssClamp = d.MssClamp.ValueString()
|
|
model.MssClampMss = int(d.MssClampMss.ValueInt64())
|
|
model.OffloadAccounting = d.OffloadAccounting.ValueBool()
|
|
model.OffloadL2Blocking = d.OffloadL2Blocking.ValueBool()
|
|
model.OffloadSch = d.OffloadSch.ValueBool()
|
|
model.OtherTimeout = int(d.OtherTimeout.ValueInt64())
|
|
model.TimeoutSettingPreference = d.TimeoutSettingPreference.ValueString()
|
|
model.ReceiveRedirects = d.ReceiveRedirects.ValueBool()
|
|
model.SendRedirects = d.SendRedirects.ValueBool()
|
|
model.SynCookies = d.SynCookies.ValueBool()
|
|
model.UDPOtherTimeout = int(d.UdpOtherTimeout.ValueInt64())
|
|
model.UDPStreamTimeout = int(d.UdpStreamTimeout.ValueInt64())
|
|
model.UnbindWANMonitors = d.UnbindWanMonitors.ValueBool()
|
|
return model, diags
|
|
}
|
|
|
|
func (d *usgModel) Merge(ctx context.Context, other interface{}) diag.Diagnostics {
|
|
diags := diag.Diagnostics{}
|
|
|
|
model, ok := other.(*unifi.SettingUsg)
|
|
if !ok {
|
|
diags.AddError("Cannot merge", "Cannot merge type that is not *unifi.SettingUsg")
|
|
return diags
|
|
}
|
|
|
|
d.ID = types.StringValue(model.ID)
|
|
d.MulticastDnsEnabled = types.BoolValue(model.MdnsEnabled)
|
|
|
|
// Set Geo IP filtering attributes
|
|
d.GeoIPFilteringEnabled = types.BoolValue(model.GeoIPFilteringEnabled)
|
|
if model.GeoIPFilteringEnabled {
|
|
geoIPFiltering := &GeoIPFilteringModel{
|
|
Mode: types.StringValue(model.GeoIPFilteringBlock),
|
|
TrafficDirection: types.StringValue(model.GeoIPFilteringTrafficDirection),
|
|
}
|
|
|
|
countries, diags := ut.StringToListElements(ctx, model.GeoIPFilteringCountries)
|
|
if diags.HasError() {
|
|
return diags
|
|
}
|
|
geoIPFiltering.Countries = countries
|
|
|
|
geoIPObject, diags := types.ObjectValueFrom(ctx, geoIPFiltering.AttributeTypes(), geoIPFiltering)
|
|
if diags.HasError() {
|
|
return diags
|
|
}
|
|
d.GeoIPFiltering = geoIPObject
|
|
} else {
|
|
d.GeoIPFiltering = types.ObjectNull((&GeoIPFilteringModel{}).AttributeTypes())
|
|
}
|
|
|
|
d.UpnpEnabled = types.BoolValue(model.UpnpEnabled)
|
|
// Set UPNP attributes
|
|
if model.UpnpEnabled {
|
|
upnp := &UpnpModel{
|
|
NatPmpEnabled: types.BoolValue(model.UpnpNATPmpEnabled),
|
|
SecureMode: types.BoolValue(model.UpnpSecureMode),
|
|
WANInterface: types.StringValue(model.UpnpWANInterface),
|
|
}
|
|
|
|
upnpObject, diags := types.ObjectValueFrom(ctx, upnp.AttributeTypes(), upnp)
|
|
if diags.HasError() {
|
|
return diags
|
|
}
|
|
d.Upnp = upnpObject
|
|
} else {
|
|
d.Upnp = types.ObjectNull((&UpnpModel{}).AttributeTypes())
|
|
}
|
|
|
|
// Convert DNS Verification settings
|
|
dnsVerificationModel := DNSVerificationModel{
|
|
Domain: types.StringValue(model.DNSVerification.Domain),
|
|
PrimaryDNSServer: types.StringValue(model.DNSVerification.PrimaryDNSServer),
|
|
SecondaryDNSServer: types.StringValue(model.DNSVerification.SecondaryDNSServer),
|
|
SettingPreference: types.StringValue(model.DNSVerification.SettingPreference),
|
|
}
|
|
dnsVerificationObj, dnsVerificationObjDiags := types.ObjectValueFrom(ctx, dnsVerificationModel.AttributeTypes(), &dnsVerificationModel)
|
|
diags.Append(dnsVerificationObjDiags...)
|
|
|
|
d.DnsVerification = dnsVerificationObj
|
|
// Convert TCP Timeout settings
|
|
tcpTimeoutModel := TCPTimeoutModel{
|
|
CloseTimeout: types.Int64Value(int64(model.TCPCloseTimeout)),
|
|
CloseWaitTimeout: types.Int64Value(int64(model.TCPCloseWaitTimeout)),
|
|
EstablishedTimeout: types.Int64Value(int64(model.TCPEstablishedTimeout)),
|
|
FinWaitTimeout: types.Int64Value(int64(model.TCPFinWaitTimeout)),
|
|
LastAckTimeout: types.Int64Value(int64(model.TCPLastAckTimeout)),
|
|
SynRecvTimeout: types.Int64Value(int64(model.TCPSynRecvTimeout)),
|
|
SynSentTimeout: types.Int64Value(int64(model.TCPSynSentTimeout)),
|
|
TimeWaitTimeout: types.Int64Value(int64(model.TCPTimeWaitTimeout)),
|
|
}
|
|
|
|
tcpTimeoutObj, tcpTimeoutObjDiags := types.ObjectValueFrom(ctx, tcpTimeoutModel.AttributeTypes(), &tcpTimeoutModel)
|
|
diags.Append(tcpTimeoutObjDiags...)
|
|
d.TcpTimeouts = tcpTimeoutObj
|
|
|
|
// Convert DHCP Relay settings
|
|
dhcpRelayModel := DHCPRelayModel{
|
|
AgentsPackets: types.StringValue(model.DHCPRelayAgentsPackets),
|
|
HopCount: types.Int64Value(int64(model.DHCPRelayHopCount)),
|
|
MaxSize: types.Int64Value(int64(model.DHCPRelayMaxSize)),
|
|
Port: types.Int64Value(int64(model.DHCPRelayPort)),
|
|
}
|
|
|
|
// TODO deprecated
|
|
|
|
// Extract non-empty DHCP relay servers
|
|
dhcpRelay := []string{}
|
|
for _, s := range []string{
|
|
model.DHCPRelayServer1,
|
|
model.DHCPRelayServer2,
|
|
model.DHCPRelayServer3,
|
|
model.DHCPRelayServer4,
|
|
model.DHCPRelayServer5,
|
|
} {
|
|
if s == "" {
|
|
continue
|
|
}
|
|
dhcpRelay = append(dhcpRelay, s)
|
|
}
|
|
|
|
// Set the DHCP relay servers list
|
|
dhcpRelayServers, diags := types.ListValueFrom(ctx, types.StringType, dhcpRelay)
|
|
if diags.HasError() {
|
|
return diags
|
|
}
|
|
d.DhcpRelayServers = dhcpRelayServers
|
|
// TODO end of deprecated
|
|
dhcpRelayObj, dhcpRelayObjDiags := types.ObjectValueFrom(ctx, dhcpRelayModel.AttributeTypes(), &dhcpRelayModel)
|
|
diags.Append(dhcpRelayObjDiags...)
|
|
d.DhcpRelay = dhcpRelayObj
|
|
|
|
// Set all flat attributes
|
|
d.ArpCacheBaseReachable = types.Int64Value(int64(model.ArpCacheBaseReachable))
|
|
d.ArpCacheTimeout = types.StringValue(model.ArpCacheTimeout)
|
|
d.BroadcastPing = types.BoolValue(model.BroadcastPing)
|
|
d.DhcpdHostfileUpdate = types.BoolValue(model.DHCPDHostfileUpdate)
|
|
d.DhcpdUseDnsmasq = types.BoolValue(model.DHCPDUseDNSmasq)
|
|
d.DnsmasqAllServers = types.BoolValue(model.DNSmasqAllServers)
|
|
d.EchoServer = types.StringValue(model.EchoServer)
|
|
d.FtpModule = types.BoolValue(model.FtpModule)
|
|
d.GreModule = types.BoolValue(model.GreModule)
|
|
d.H323Module = types.BoolValue(model.H323Module)
|
|
d.PptpModule = types.BoolValue(model.PptpModule)
|
|
d.SipModule = types.BoolValue(model.SipModule)
|
|
d.TftpModule = types.BoolValue(model.TFTPModule)
|
|
d.IcmpTimeout = types.Int64Value(int64(model.ICMPTimeout))
|
|
d.LldpEnableAll = types.BoolValue(model.LldpEnableAll)
|
|
d.MssClamp = types.StringValue(model.MssClamp)
|
|
d.MssClampMss = types.Int64Value(int64(model.MssClampMss))
|
|
d.OffloadAccounting = types.BoolValue(model.OffloadAccounting)
|
|
d.OffloadL2Blocking = types.BoolValue(model.OffloadL2Blocking)
|
|
d.OffloadSch = types.BoolValue(model.OffloadSch)
|
|
d.OtherTimeout = types.Int64Value(int64(model.OtherTimeout))
|
|
d.TimeoutSettingPreference = types.StringValue(model.TimeoutSettingPreference)
|
|
d.ReceiveRedirects = types.BoolValue(model.ReceiveRedirects)
|
|
d.SendRedirects = types.BoolValue(model.SendRedirects)
|
|
d.SynCookies = types.BoolValue(model.SynCookies)
|
|
d.UdpOtherTimeout = types.Int64Value(int64(model.UDPOtherTimeout))
|
|
d.UdpStreamTimeout = types.Int64Value(int64(model.UDPStreamTimeout))
|
|
d.UnbindWanMonitors = types.BoolValue(model.UnbindWANMonitors)
|
|
return diags
|
|
}
|
|
|
|
func (r *usgResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
|
|
resp.Schema = schema.Schema{
|
|
MarkdownDescription: "The `unifi_setting_usg` resource manages advanced settings for UniFi Security Gateways (USG) and UniFi Dream Machines (UDM/UDM-Pro).\n\n" +
|
|
"This resource allows you to configure gateway-specific features including:\n" +
|
|
" * Multicast DNS (mDNS) for cross-VLAN service discovery\n" +
|
|
" * DHCP relay for forwarding DHCP requests to external servers\n" +
|
|
" * Geo IP filtering for country-based traffic control\n" +
|
|
" * UPNP/NAT-PMP for automatic port forwarding\n" +
|
|
" * Protocol helpers for FTP, GRE, H323, PPTP, SIP, and TFTP\n" +
|
|
" * TCP/UDP timeout settings for connection tracking\n" +
|
|
" * Security features like SYN cookies and ICMP redirect controls\n" +
|
|
" * MSS clamping for optimizing MTU issues\n\n" +
|
|
"Note: Some settings may not be available on all controller versions. For example, multicast_dns_enabled is not supported on UniFi OS v7+. Changes to certain attributes may not be reflected in the plan unless explicitly modified in the configuration.",
|
|
Attributes: map[string]schema.Attribute{
|
|
"id": ut.ID(),
|
|
"site": ut.SiteAttribute(),
|
|
"multicast_dns_enabled": schema.BoolAttribute{
|
|
MarkdownDescription: "Enable multicast DNS (mDNS/Bonjour/Avahi) forwarding across VLANs. This allows devices to discover services " +
|
|
"(like printers, Chromecasts, Apple devices, etc.) even when they are on different networks or VLANs. " +
|
|
"When enabled, the gateway will forward mDNS packets between networks, facilitating cross-VLAN service discovery. " +
|
|
"Note: This setting is not supported on UniFi OS v7+ as it has been replaced by mDNS settings in the network configuration.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Bool{
|
|
boolplanmodifier.UseStateForUnknown(),
|
|
},
|
|
},
|
|
"dhcp_relay_servers": schema.ListAttribute{
|
|
MarkdownDescription: "List of up to 5 DHCP relay servers (specified by IP address) that will receive forwarded DHCP requests. " +
|
|
"This is useful when you want to use external DHCP servers instead of the built-in DHCP server on the USG/UDM. " +
|
|
"When configured, the gateway will forward DHCP discovery packets from clients to these external servers, allowing " +
|
|
"centralized IP address management across multiple networks. " +
|
|
"Example: `['192.168.1.5', '192.168.2.5']`",
|
|
DeprecationMessage: "This attribute is deprecated and will be removed in a future release. `dhcp_relay.servers` attribute will be introduced as a replacement.",
|
|
ElementType: types.StringType,
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.List{
|
|
listplanmodifier.UseStateForUnknown(),
|
|
},
|
|
Default: ut.DefaultEmptyList(types.StringType),
|
|
Validators: []validator.List{
|
|
listvalidator.SizeAtMost(5),
|
|
listvalidator.ValueStringsAre(validators.IPv4()),
|
|
},
|
|
},
|
|
"dhcp_relay": schema.SingleNestedAttribute{
|
|
MarkdownDescription: "Advanced DHCP relay configuration settings. Controls how the gateway forwards DHCP requests to external servers " +
|
|
"and manages DHCP relay agent behavior. Use this block to fine-tune DHCP relay functionality beyond simply specifying relay servers.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Object{
|
|
objectplanmodifier.UseStateForUnknown(),
|
|
},
|
|
Attributes: map[string]schema.Attribute{
|
|
"agents_packets": schema.StringAttribute{
|
|
MarkdownDescription: "Specifies how to handle DHCP relay agent information in packets. Valid values are:\n" +
|
|
" * `append` - Add relay agent information to packets that may already contain it\n" +
|
|
" * `discard` - Drop packets that already contain relay agent information\n" +
|
|
" * `forward` - Forward packets regardless of relay agent information\n" +
|
|
" * `replace` - Replace existing relay agent information with the gateway's information",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.String{
|
|
stringplanmodifier.UseStateForUnknown(),
|
|
},
|
|
Validators: []validator.String{
|
|
stringvalidator.OneOf("append", "discard", "forward", "replace"),
|
|
},
|
|
},
|
|
"hop_count": schema.Int64Attribute{
|
|
MarkdownDescription: "Maximum number of relay agents that can forward the DHCP packet before it is discarded. " +
|
|
"This prevents DHCP packets from being forwarded indefinitely in complex network topologies. " +
|
|
"Valid values range from 1 to 255, with lower values recommended for simpler networks.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Int64{
|
|
int64planmodifier.UseStateForUnknown(),
|
|
},
|
|
Validators: []validator.Int64{
|
|
int64validator.Between(1, 255),
|
|
},
|
|
},
|
|
"max_size": schema.Int64Attribute{
|
|
MarkdownDescription: "Maximum size (in bytes) of DHCP relay packets that will be forwarded. " +
|
|
"Packets exceeding this size will be truncated or dropped. Valid values range from 64 to 1400 bytes. " +
|
|
"The default is typically sufficient for most DHCP implementations, but may need adjustment if using " +
|
|
"extensive DHCP options or vendor-specific information.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Int64{
|
|
int64planmodifier.UseStateForUnknown(),
|
|
},
|
|
Validators: []validator.Int64{
|
|
int64validator.Between(64, 1400),
|
|
},
|
|
},
|
|
"port": schema.Int64Attribute{
|
|
MarkdownDescription: "UDP port number for the DHCP relay service to listen on. The standard DHCP server port is 67, " +
|
|
"but this can be customized if needed for specific network configurations. Valid values range from 1 to 65535. " +
|
|
"Ensure this doesn't conflict with other services running on the gateway.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Int64{
|
|
int64planmodifier.UseStateForUnknown(),
|
|
},
|
|
Validators: []validator.Int64{
|
|
int64validator.Between(1, 65535),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
"geo_ip_filtering_enabled": schema.BoolAttribute{
|
|
MarkdownDescription: "Whether Geo IP Filtering is enabled. When enabled, the gateway will apply the specified country-based ",
|
|
Computed: true,
|
|
},
|
|
"geo_ip_filtering": schema.SingleNestedAttribute{
|
|
MarkdownDescription: "Geographic IP filtering configuration that allows blocking or allowing traffic based on country of origin. " +
|
|
"This feature uses IP geolocation databases to identify the country associated with IP addresses and apply filtering rules. " +
|
|
"Useful for implementing country-specific access policies or blocking traffic from high-risk regions. Requires controller version 7.0 or later.",
|
|
Optional: true,
|
|
Attributes: map[string]schema.Attribute{
|
|
"mode": schema.StringAttribute{
|
|
MarkdownDescription: "Specifies whether the selected countries should be blocked or allowed. Valid values are:\n" +
|
|
" * `block` (default) - Traffic from the specified countries will be blocked, while traffic from all other countries will be allowed\n" +
|
|
" * `allow` - Only traffic from the specified countries will be allowed, while traffic from all other countries will be blocked\n\n" +
|
|
"This setting effectively determines whether the `countries` list functions as a blocklist or an allowlist.",
|
|
Optional: true,
|
|
Computed: true,
|
|
Default: stringdefault.StaticString("block"),
|
|
PlanModifiers: []planmodifier.String{
|
|
stringplanmodifier.UseStateForUnknown(),
|
|
},
|
|
Validators: []validator.String{
|
|
stringvalidator.OneOf("block", "allow"),
|
|
},
|
|
},
|
|
"countries": schema.ListAttribute{
|
|
MarkdownDescription: "List of two-letter ISO 3166-1 alpha-2 country codes to block or allow, depending on the `block` setting. " +
|
|
"Must contain at least one country code when geo IP filtering is enabled. Country codes are case-insensitive but are typically " +
|
|
"written in uppercase.\n\n" +
|
|
"Examples:\n" +
|
|
" * `['US', 'CA', 'MX']` - United States, Canada, and Mexico\n" +
|
|
" * `['CN', 'RU', 'IR']` - China, Russia, and Iran\n" +
|
|
" * `['GB', 'DE', 'FR']` - United Kingdom, Germany, and France",
|
|
Required: true,
|
|
ElementType: types.StringType,
|
|
Validators: []validator.List{
|
|
listvalidator.SizeAtLeast(1),
|
|
listvalidator.ValueStringsAre(validators.CountryCodeAlpha2()),
|
|
},
|
|
},
|
|
"traffic_direction": schema.StringAttribute{
|
|
MarkdownDescription: "Specifies which traffic direction the geo IP filtering applies to. Valid values are:\n" +
|
|
" * `both` (default) - Filters traffic in both directions (incoming and outgoing)\n" +
|
|
" * `ingress` - Filters only incoming traffic (from WAN to LAN)\n" +
|
|
" * `egress` - Filters only outgoing traffic (from LAN to WAN)\n\n" +
|
|
"This setting is useful for creating more granular filtering policies. For example, you might want to block incoming traffic " +
|
|
"from certain countries while still allowing outgoing connections to those same countries.",
|
|
Optional: true,
|
|
Computed: true,
|
|
Default: stringdefault.StaticString("both"),
|
|
PlanModifiers: []planmodifier.String{
|
|
stringplanmodifier.UseStateForUnknown(),
|
|
},
|
|
Validators: []validator.String{
|
|
stringvalidator.OneOf("both", "ingress", "egress"),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
"upnp_enabled": schema.BoolAttribute{
|
|
MarkdownDescription: "Whether UPNP is enabled. When enabled, the gateway will automatically forward ports for UPNP-compatible devices ",
|
|
Computed: true,
|
|
},
|
|
"upnp": schema.SingleNestedAttribute{
|
|
MarkdownDescription: "UPNP (Universal Plug and Play) configuration settings. UPNP allows compatible applications and devices to automatically " +
|
|
"configure port forwarding rules on the gateway without manual intervention. This is commonly used by gaming consoles, " +
|
|
"media servers, VoIP applications, and other network services that require incoming connections.",
|
|
Optional: true,
|
|
Attributes: map[string]schema.Attribute{
|
|
"nat_pmp_enabled": schema.BoolAttribute{
|
|
MarkdownDescription: "Enable NAT-PMP (NAT Port Mapping Protocol) support alongside UPNP. NAT-PMP is " +
|
|
"Apple's alternative to UPNP, providing similar automatic port mapping capabilities. When enabled, Apple devices " +
|
|
"like Macs, iPhones, and iPads can automatically configure port forwarding for services like AirPlay, FaceTime, " +
|
|
"iMessage, and other Apple services. Defaults to `false`.",
|
|
Optional: true,
|
|
Computed: true,
|
|
Default: booldefault.StaticBool(false),
|
|
},
|
|
"secure_mode": schema.BoolAttribute{
|
|
MarkdownDescription: "Enable secure mode for UPNP. In secure mode, the gateway only forwards ports " +
|
|
"to the device that specifically requested them, enhancing security. This prevents malicious applications from " +
|
|
"redirecting ports to different devices than intended. It's strongly recommended to enable this setting when using UPNP " +
|
|
"to minimize security risks. Defaults to `false`.",
|
|
Optional: true,
|
|
Computed: true,
|
|
Default: booldefault.StaticBool(false),
|
|
},
|
|
"wan_interface": schema.StringAttribute{
|
|
MarkdownDescription: "Specify which WAN interface to use for UPNP service. Valid values are:\n" +
|
|
" * `WAN` (default) - Use the primary WAN interface for UPNP port forwarding\n" +
|
|
" * `WAN2` - Use the secondary WAN interface for UPNP port forwarding (if available)\n\n" +
|
|
"This setting is particularly relevant for dual-WAN setups where you may want to direct UPNP traffic through " +
|
|
"a specific WAN connection. If your gateway only has a single WAN interface, use the default `WAN` setting.",
|
|
Optional: true,
|
|
Computed: true,
|
|
Default: stringdefault.StaticString("WAN"),
|
|
Validators: []validator.String{
|
|
stringvalidator.OneOf("WAN", "WAN2"),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
// ARP Cache Configuration
|
|
"arp_cache_base_reachable": schema.Int64Attribute{
|
|
MarkdownDescription: "The base reachable timeout (in seconds) for ARP cache entries. This controls how long the gateway considers " +
|
|
"a MAC-to-IP mapping valid without needing to refresh it. Higher values reduce network traffic but may cause stale " +
|
|
"entries if devices change IP addresses frequently.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Int64{
|
|
int64planmodifier.UseStateForUnknown(),
|
|
},
|
|
},
|
|
"arp_cache_timeout": schema.StringAttribute{
|
|
MarkdownDescription: "The timeout strategy for ARP cache entries. Valid values are:\n" +
|
|
" * `normal` - Use system default timeouts\n" +
|
|
" * `min-dhcp-lease` - Set ARP timeout to match the minimum DHCP lease time\n" +
|
|
" * `custom` - Use the custom timeout value specified in `arp_cache_base_reachable`\n\n" +
|
|
"This setting determines how long MAC-to-IP mappings are stored in the ARP cache before being refreshed.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.String{
|
|
stringplanmodifier.UseStateForUnknown(),
|
|
},
|
|
},
|
|
|
|
// DHCP Configuration
|
|
"broadcast_ping": schema.BoolAttribute{
|
|
MarkdownDescription: "Enable responding to broadcast ping requests (ICMP echo requests sent to the broadcast address). " +
|
|
"When enabled, the gateway will respond to pings sent to the broadcast address of the network (e.g., 192.168.1.255). " +
|
|
"This can be useful for network diagnostics but may also be used in certain denial-of-service attacks.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Bool{
|
|
boolplanmodifier.UseStateForUnknown(),
|
|
},
|
|
},
|
|
"dhcpd_hostfile_update": schema.BoolAttribute{
|
|
MarkdownDescription: "Enable updating the gateway's host files with DHCP client information. When enabled, the gateway will " +
|
|
"automatically add entries to its host file for each DHCP client, allowing hostname resolution for devices " +
|
|
"that receive IP addresses via DHCP. This improves name resolution on the local network.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Bool{
|
|
boolplanmodifier.UseStateForUnknown(),
|
|
},
|
|
},
|
|
"dhcpd_use_dnsmasq": schema.BoolAttribute{
|
|
MarkdownDescription: "Use dnsmasq for DHCP services instead of the default DHCP server. Dnsmasq provides integrated DNS and DHCP " +
|
|
"functionality with additional features like DNS caching, DHCP static leases, and local domain name resolution. " +
|
|
"This can improve DNS resolution performance and provide more flexible DHCP options.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Bool{
|
|
boolplanmodifier.UseStateForUnknown(),
|
|
},
|
|
},
|
|
"dnsmasq_all_servers": schema.BoolAttribute{
|
|
MarkdownDescription: "When enabled, dnsmasq will query all configured DNS servers simultaneously and use the fastest response. " +
|
|
"This can improve DNS resolution speed but may increase DNS traffic. By default, dnsmasq queries servers " +
|
|
"sequentially, only trying the next server if the current one fails to respond.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Bool{
|
|
boolplanmodifier.UseStateForUnknown(),
|
|
},
|
|
},
|
|
|
|
// DNS Verification
|
|
"dns_verification": schema.SingleNestedAttribute{
|
|
MarkdownDescription: "DNS verification settings for validating DNS responses. This feature helps detect and prevent DNS spoofing " +
|
|
"attacks by verifying DNS responses against trusted DNS servers. When configured, the gateway can compare DNS " +
|
|
"responses with those from known trusted servers to identify potential tampering or poisoning attempts. Requires controller version 8.5 or later.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Object{
|
|
objectplanmodifier.UseStateForUnknown(),
|
|
},
|
|
Validators: []validator.Object{
|
|
validators.RequiredTogetherIf(path.MatchRoot("setting_preference"), types.StringValue("manual"), path.MatchRoot("primary_dns_server"), path.MatchRoot("domain")),
|
|
validators.RequiredNoneIf(path.MatchRoot("setting_preference"), types.StringValue("auto"), path.MatchRoot("primary_dns_server"), path.MatchRoot("secondary_dns_server"), path.MatchRoot("domain")),
|
|
},
|
|
Attributes: map[string]schema.Attribute{
|
|
"domain": schema.StringAttribute{
|
|
MarkdownDescription: "The domain name to use for DNS verification tests. The gateway will query this domain when testing DNS " +
|
|
"server responses. This should be a reliable domain that is unlikely to change frequently. " +
|
|
"Required when `setting_preference` is set to `manual`.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.String{
|
|
stringplanmodifier.UseStateForUnknown(),
|
|
},
|
|
},
|
|
"primary_dns_server": schema.StringAttribute{
|
|
MarkdownDescription: "The IP address of the primary trusted DNS server to use for verification. DNS responses will be compared " +
|
|
"against responses from this server to detect potential DNS spoofing. Required when `setting_preference` is " +
|
|
"set to `manual`. Must be a valid IPv4 address.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.String{
|
|
stringplanmodifier.UseStateForUnknown(),
|
|
},
|
|
Validators: []validator.String{
|
|
validators.IPv4(),
|
|
},
|
|
},
|
|
"secondary_dns_server": schema.StringAttribute{
|
|
MarkdownDescription: "The IP address of the secondary trusted DNS server to use for verification. This server will be used " +
|
|
"if the primary server is unavailable. Optional even when `setting_preference` is set to `manual`. " +
|
|
"Must be a valid IPv4 address if specified.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.String{
|
|
stringplanmodifier.UseStateForUnknown(),
|
|
},
|
|
Validators: []validator.String{
|
|
validators.IPv4(),
|
|
},
|
|
},
|
|
"setting_preference": schema.StringAttribute{
|
|
MarkdownDescription: "Determines how DNS verification servers are configured. Valid values are:\n" +
|
|
" * `auto` - The gateway will automatically select DNS servers for verification\n" +
|
|
" * `manual` - Use the manually specified `primary_dns_server` and optionally `secondary_dns_server`\n\n" +
|
|
"When set to `manual`, you must also specify `primary_dns_server` and `domain` values.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.String{
|
|
stringplanmodifier.UseStateForUnknown(),
|
|
},
|
|
Validators: []validator.String{
|
|
stringvalidator.OneOf("auto", "manual"),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
|
|
// Network Tools
|
|
"echo_server": schema.StringAttribute{
|
|
MarkdownDescription: "The hostname or IP address of a server to use for network echo tests. Echo tests send packets to this server " +
|
|
"and measure response times to evaluate network connectivity and performance. This can be used for network " +
|
|
"diagnostics and monitoring.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.String{
|
|
stringplanmodifier.UseStateForUnknown(),
|
|
},
|
|
},
|
|
|
|
// Protocol Modules
|
|
"ftp_module": schema.BoolAttribute{
|
|
MarkdownDescription: "Enable the FTP (File Transfer Protocol) helper module. This module allows the gateway to properly handle " +
|
|
"FTP connections through NAT by tracking the control channel and dynamically opening required data ports. " +
|
|
"Without this helper, passive FTP connections may fail when clients are behind NAT.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Bool{
|
|
boolplanmodifier.UseStateForUnknown(),
|
|
},
|
|
},
|
|
"gre_module": schema.BoolAttribute{
|
|
MarkdownDescription: "Enable the GRE (Generic Routing Encapsulation) protocol helper module. This module allows proper handling " +
|
|
"of GRE tunneling protocol through the gateway's firewall. GRE is commonly used for VPN tunnels and other " +
|
|
"encapsulation needs. Required if you plan to use PPTP VPNs (see `pptp_module`).",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Bool{
|
|
boolplanmodifier.UseStateForUnknown(),
|
|
},
|
|
},
|
|
"h323_module": schema.BoolAttribute{
|
|
MarkdownDescription: "Enable the H.323 protocol helper module. H.323 is a standard for multimedia communications (audio, video, " +
|
|
"and data) over packet-based networks. This helper allows H.323-based applications like video conferencing " +
|
|
"systems to work properly through NAT by tracking connection details and opening required ports.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Bool{
|
|
boolplanmodifier.UseStateForUnknown(),
|
|
},
|
|
},
|
|
"pptp_module": schema.BoolAttribute{
|
|
MarkdownDescription: "Enable the PPTP (Point-to-Point Tunneling Protocol) helper module. This module allows PPTP VPN connections " +
|
|
"to work properly through the gateway's firewall and NAT. PPTP uses GRE for tunneling, so the `gre_module` " +
|
|
"must also be enabled for PPTP to function correctly. Note that PPTP has known security vulnerabilities and " +
|
|
"more secure VPN protocols are generally recommended.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Bool{
|
|
boolplanmodifier.UseStateForUnknown(),
|
|
},
|
|
},
|
|
"sip_module": schema.BoolAttribute{
|
|
MarkdownDescription: "Enable the SIP (Session Initiation Protocol) helper module. SIP is used for initiating, maintaining, and " +
|
|
"terminating real-time sessions for voice, video, and messaging applications (VoIP, video conferencing). " +
|
|
"This helper allows SIP-based applications to work correctly through NAT by tracking SIP connections and " +
|
|
"dynamically opening the necessary ports for media streams.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Bool{
|
|
boolplanmodifier.UseStateForUnknown(),
|
|
},
|
|
},
|
|
"tftp_module": schema.BoolAttribute{
|
|
MarkdownDescription: "Enable the TFTP (Trivial File Transfer Protocol) helper module. This module allows TFTP connections to work " +
|
|
"properly through the gateway's firewall and NAT. TFTP is commonly used for firmware updates, configuration " +
|
|
"file transfers, and network booting of devices. The helper tracks TFTP connections and ensures return traffic " +
|
|
"is properly handled.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Bool{
|
|
boolplanmodifier.UseStateForUnknown(),
|
|
},
|
|
},
|
|
|
|
// ICMP Settings
|
|
"icmp_timeout": schema.Int64Attribute{
|
|
MarkdownDescription: "ICMP timeout in seconds for connection tracking. This controls how long the gateway maintains state " +
|
|
"information for ICMP (ping) packets in its connection tracking table. Higher values maintain ICMP connection " +
|
|
"state longer, while lower values reclaim resources more quickly but may affect some diagnostic tools.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Int64{
|
|
int64planmodifier.UseStateForUnknown(),
|
|
},
|
|
},
|
|
|
|
// LLDP Settings
|
|
"lldp_enable_all": schema.BoolAttribute{
|
|
MarkdownDescription: "Enable Link Layer Discovery Protocol (LLDP) on all interfaces. LLDP is a vendor-neutral protocol that " +
|
|
"allows network devices to advertise their identity, capabilities, and neighbors on a local network. When enabled, " +
|
|
"the gateway will both send and receive LLDP packets, facilitating network discovery and management tools.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Bool{
|
|
boolplanmodifier.UseStateForUnknown(),
|
|
},
|
|
},
|
|
|
|
// MSS Clamp Settings
|
|
"mss_clamp": schema.StringAttribute{
|
|
MarkdownDescription: "TCP Maximum Segment Size (MSS) clamping mode. MSS clamping adjusts the maximum segment size of TCP packets " +
|
|
"to prevent fragmentation issues when packets traverse networks with different MTU sizes. Valid values include:\n" +
|
|
" * `auto` - Automatically determine appropriate MSS values based on interface MTUs\n" +
|
|
" * `custom` - Use the custom MSS value specified in `mss_clamp_mss`\n" +
|
|
" * `disabled` - Do not perform MSS clamping\n\n" +
|
|
"This setting is particularly important for VPN connections and networks with non-standard MTU sizes.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.String{
|
|
stringplanmodifier.UseStateForUnknown(),
|
|
},
|
|
},
|
|
"mss_clamp_mss": schema.Int64Attribute{
|
|
MarkdownDescription: "Custom TCP Maximum Segment Size (MSS) value in bytes. This value is used when `mss_clamp` is set to `custom`. " +
|
|
"The MSS value should typically be set to the path MTU minus 40 bytes (for IPv4) or minus 60 bytes (for IPv6) to account " +
|
|
"for TCP/IP header overhead. Valid values range from 100 to 9999, with common values being 1460 (for standard 1500 MTU) " +
|
|
"or 1400 (for VPN tunnels).",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Int64{
|
|
int64planmodifier.UseStateForUnknown(),
|
|
},
|
|
Validators: []validator.Int64{
|
|
int64validator.Between(100, 9999),
|
|
},
|
|
},
|
|
|
|
// Offload Settings
|
|
"offload_accounting": schema.BoolAttribute{
|
|
MarkdownDescription: "Enable hardware accounting offload. When enabled, the gateway will use hardware acceleration for traffic " +
|
|
"accounting functions, reducing CPU load and potentially improving throughput for high-traffic environments. " +
|
|
"This setting may not be supported on all hardware models.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Bool{
|
|
boolplanmodifier.UseStateForUnknown(),
|
|
},
|
|
},
|
|
"offload_l2_blocking": schema.BoolAttribute{
|
|
MarkdownDescription: "Enable hardware offload for Layer 2 (L2) blocking functions. When enabled, the gateway will use hardware " +
|
|
"acceleration for blocking traffic at the data link layer (MAC address level), which can improve performance " +
|
|
"when implementing MAC-based filtering or isolation. This setting may not be supported on all hardware models.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Bool{
|
|
boolplanmodifier.UseStateForUnknown(),
|
|
},
|
|
},
|
|
"offload_sch": schema.BoolAttribute{
|
|
MarkdownDescription: "Enable hardware scheduling offload. When enabled, the gateway will use hardware acceleration for packet " +
|
|
"scheduling functions, which can improve QoS (Quality of Service) performance and throughput for prioritized traffic. " +
|
|
"This setting may not be supported on all hardware models and may affect other hardware offload capabilities.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Bool{
|
|
boolplanmodifier.UseStateForUnknown(),
|
|
},
|
|
},
|
|
|
|
// Timeout Settings
|
|
"other_timeout": schema.Int64Attribute{
|
|
MarkdownDescription: "Timeout (in seconds) for connection tracking of protocols other than TCP, UDP, and ICMP. This controls how long " +
|
|
"the gateway maintains state information for connections using other protocols. Higher values maintain connection state " +
|
|
"longer, while lower values reclaim resources more quickly but may affect some applications using non-standard protocols.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Int64{
|
|
int64planmodifier.UseStateForUnknown(),
|
|
},
|
|
},
|
|
"timeout_setting_preference": schema.StringAttribute{
|
|
MarkdownDescription: "Determines how connection timeout values are configured. Valid values are:\n" +
|
|
" * `auto` - The gateway will automatically determine appropriate timeout values based on system defaults\n" +
|
|
" * `manual` - Use the manually specified timeout values for various connection types\n\n" +
|
|
"When set to `manual`, you should specify values for the various timeout settings like `tcp_timeouts`, " +
|
|
"`udp_stream_timeout`, `udp_other_timeout`, `icmp_timeout`, and `other_timeout`. Requires controller version 7.0 or later.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.String{
|
|
stringplanmodifier.UseStateForUnknown(),
|
|
},
|
|
Validators: []validator.String{
|
|
stringvalidator.OneOf("auto", "manual"),
|
|
},
|
|
},
|
|
|
|
// TCP Settings (nested)
|
|
"tcp_timeouts": schema.SingleNestedAttribute{
|
|
MarkdownDescription: "TCP connection timeout settings for various TCP connection states. These settings control how long the gateway " +
|
|
"maintains state information for TCP connections in different states before removing them from the connection tracking " +
|
|
"table. Proper timeout values balance resource usage with connection reliability. These settings are particularly " +
|
|
"relevant when `timeout_setting_preference` is set to `manual`.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Object{
|
|
objectplanmodifier.UseStateForUnknown(),
|
|
},
|
|
Attributes: map[string]schema.Attribute{
|
|
"close_timeout": schema.Int64Attribute{
|
|
MarkdownDescription: "Timeout (in seconds) for TCP connections in the CLOSE state. The CLOSE state occurs when a connection is " +
|
|
"being terminated but may still have packets in transit. Lower values reclaim resources more quickly, while higher " +
|
|
"values ensure all packets are properly processed during connection termination.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Int64{
|
|
int64planmodifier.UseStateForUnknown(),
|
|
},
|
|
},
|
|
"close_wait_timeout": schema.Int64Attribute{
|
|
MarkdownDescription: "Timeout (in seconds) for TCP connections in the CLOSE_WAIT state. The CLOSE_WAIT state occurs when the remote " +
|
|
"end has initiated connection termination, but the local application hasn't closed the connection yet. This timeout " +
|
|
"prevents resources from being held indefinitely if a local application fails to properly close its connection.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Int64{
|
|
int64planmodifier.UseStateForUnknown(),
|
|
},
|
|
},
|
|
"established_timeout": schema.Int64Attribute{
|
|
MarkdownDescription: "Timeout (in seconds) for TCP connections in the ESTABLISHED state. This is the most important TCP timeout as it " +
|
|
"determines how long idle but established connections are maintained in the connection tracking table. Higher values " +
|
|
"(e.g., 86400 = 24 hours) are suitable for long-lived connections, while lower values conserve resources but may cause " +
|
|
"issues with applications that maintain idle connections.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Int64{
|
|
int64planmodifier.UseStateForUnknown(),
|
|
},
|
|
},
|
|
"fin_wait_timeout": schema.Int64Attribute{
|
|
MarkdownDescription: "Timeout (in seconds) for TCP connections in the FIN_WAIT state. The FIN_WAIT states occur during the normal " +
|
|
"TCP connection termination process after a FIN packet has been sent. This timeout prevents resources from being held " +
|
|
"if the connection termination process doesn't complete properly.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Int64{
|
|
int64planmodifier.UseStateForUnknown(),
|
|
},
|
|
},
|
|
"last_ack_timeout": schema.Int64Attribute{
|
|
MarkdownDescription: "Timeout (in seconds) for TCP connections in the LAST_ACK state. The LAST_ACK state occurs during connection " +
|
|
"termination when the remote end has sent a FIN, the local end has responded with a FIN and ACK, and is waiting for " +
|
|
"the final ACK from the remote end to complete the connection termination.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Int64{
|
|
int64planmodifier.UseStateForUnknown(),
|
|
},
|
|
},
|
|
"syn_recv_timeout": schema.Int64Attribute{
|
|
MarkdownDescription: "Timeout (in seconds) for TCP connections in the SYN_RECV state. This state occurs during connection establishment " +
|
|
"after receiving a SYN packet and sending a SYN-ACK, but before receiving the final ACK to complete the three-way " +
|
|
"handshake. A lower timeout helps mitigate SYN flood attacks by releasing resources for incomplete connections more quickly.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Int64{
|
|
int64planmodifier.UseStateForUnknown(),
|
|
},
|
|
},
|
|
"syn_sent_timeout": schema.Int64Attribute{
|
|
MarkdownDescription: "Timeout (in seconds) for TCP connections in the SYN_SENT state. This state occurs during connection establishment " +
|
|
"after sending a SYN packet but before receiving a SYN-ACK response. This timeout determines how long the system will " +
|
|
"wait for a response to connection attempts before giving up.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Int64{
|
|
int64planmodifier.UseStateForUnknown(),
|
|
},
|
|
},
|
|
"time_wait_timeout": schema.Int64Attribute{
|
|
MarkdownDescription: "Timeout (in seconds) for TCP connections in the TIME_WAIT state. The TIME_WAIT state occurs after a connection " +
|
|
"has been closed but is maintained to ensure any delayed packets are properly handled. The standard recommendation is " +
|
|
"2 minutes (120 seconds), but can be reduced in high-connection environments to free resources more quickly at the " +
|
|
"risk of potential connection issues if delayed packets arrive.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Int64{
|
|
int64planmodifier.UseStateForUnknown(),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
|
|
// Redirects
|
|
"receive_redirects": schema.BoolAttribute{
|
|
MarkdownDescription: "Enable accepting ICMP redirect messages. ICMP redirects are messages sent by routers to inform hosts of better " +
|
|
"routes to specific destinations. When enabled, the gateway will update its routing table based on these messages. " +
|
|
"While useful for route optimization, this can potentially be exploited for man-in-the-middle attacks, so it's often " +
|
|
"disabled in security-sensitive environments.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Bool{
|
|
boolplanmodifier.UseStateForUnknown(),
|
|
},
|
|
},
|
|
"send_redirects": schema.BoolAttribute{
|
|
MarkdownDescription: "Enable sending ICMP redirect messages. When enabled, the gateway will send ICMP redirect messages to hosts on the " +
|
|
"local network to inform them of better routes to specific destinations. This can help optimize network traffic but " +
|
|
"is typically only needed when the gateway has multiple interfaces on the same subnet or in complex routing scenarios.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Bool{
|
|
boolplanmodifier.UseStateForUnknown(),
|
|
},
|
|
},
|
|
|
|
// Security Settings
|
|
"syn_cookies": schema.BoolAttribute{
|
|
MarkdownDescription: "Enable SYN cookies to protect against SYN flood attacks. SYN cookies are a technique that helps mitigate TCP SYN " +
|
|
"flood attacks by avoiding the need to track incomplete connections in a backlog queue. When enabled, the gateway can " +
|
|
"continue to establish legitimate connections even when under a SYN flood attack. This is a recommended security setting " +
|
|
"for internet-facing gateways.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Bool{
|
|
boolplanmodifier.UseStateForUnknown(),
|
|
},
|
|
},
|
|
|
|
// UDP Settings
|
|
"udp_other_timeout": schema.Int64Attribute{
|
|
MarkdownDescription: "Timeout (in seconds) for general UDP connections. Since UDP is connectionless, this timeout determines how long the " +
|
|
"gateway maintains state information for UDP packets that don't match the criteria for stream connections. This applies " +
|
|
"to most short-lived UDP communications like DNS queries. Lower values free resources more quickly but may affect some " +
|
|
"applications that expect longer session persistence.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Int64{
|
|
int64planmodifier.UseStateForUnknown(),
|
|
},
|
|
},
|
|
"udp_stream_timeout": schema.Int64Attribute{
|
|
MarkdownDescription: "Timeout (in seconds) for UDP stream connections. This applies to UDP traffic patterns that resemble ongoing streams, " +
|
|
"such as VoIP calls, video streaming, or online gaming. The gateway identifies these based on traffic patterns and " +
|
|
"maintains state information longer than for regular UDP traffic. Higher values improve reliability for streaming " +
|
|
"applications but consume more connection tracking resources.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Int64{
|
|
int64planmodifier.UseStateForUnknown(),
|
|
},
|
|
},
|
|
|
|
// WAN Settings
|
|
"unbind_wan_monitors": schema.BoolAttribute{
|
|
MarkdownDescription: "Unbind WAN monitors to prevent unnecessary traffic. When enabled, the gateway will stop certain monitoring processes " +
|
|
"that periodically check WAN connectivity. This can reduce unnecessary traffic on metered connections or in environments " +
|
|
"where the monitoring traffic might trigger security alerts. However, disabling these monitors may affect the gateway's " +
|
|
"ability to detect and respond to WAN connectivity issues. Requires controller version 9.0 or later.",
|
|
Optional: true,
|
|
Computed: true,
|
|
PlanModifiers: []planmodifier.Bool{
|
|
boolplanmodifier.UseStateForUnknown(),
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
// NewUsgResource creates a new instance of the USG resource.
|
|
func NewUsgResource() resource.Resource {
|
|
r := &usgResource{}
|
|
r.GenericResource = NewSettingResource(
|
|
"unifi_setting_usg",
|
|
func() *usgModel { return &usgModel{} },
|
|
func(ctx context.Context, client *base.Client, site string) (interface{}, error) {
|
|
return client.GetSettingUsg(ctx, site)
|
|
},
|
|
func(ctx context.Context, client *base.Client, site string, body interface{}) (interface{}, error) {
|
|
return client.UpdateSettingUsg(ctx, site, body.(*unifi.SettingUsg))
|
|
},
|
|
)
|
|
return r
|
|
}
|
|
|
|
var (
|
|
_ base.ResourceModel = &usgModel{}
|
|
_ resource.Resource = &usgResource{}
|
|
_ resource.ResourceWithConfigure = &usgResource{}
|
|
_ resource.ResourceWithImportState = &usgResource{}
|
|
_ resource.ResourceWithModifyPlan = &usgResource{}
|
|
_ resource.ResourceWithConfigValidators = &usgResource{}
|
|
)
|
|
|
|
type usgResource struct {
|
|
*base.GenericResource[*usgModel]
|
|
}
|
|
|
|
func (r *usgResource) ConfigValidators(ctx context.Context) []resource.ConfigValidator {
|
|
return []resource.ConfigValidator{
|
|
validators.RequiredValueIf(path.MatchRoot("pptp_module"), types.BoolValue(true), path.MatchRoot("gre_module"), types.BoolValue(true)),
|
|
}
|
|
}
|
|
|
|
func (r *usgResource) ModifyPlan(ctx context.Context, req resource.ModifyPlanRequest, resp *resource.ModifyPlanResponse) {
|
|
resp.Diagnostics.Append(r.RequireMaxVersionForPath("7.0", path.Root("multicast_dns_enabled"), req.Config)...)
|
|
resp.Diagnostics.Append(r.RequireMinVersionForPath("7.0", path.Root("timeout_setting_preference"), req.Config)...)
|
|
resp.Diagnostics.Append(r.RequireMinVersionForPath("7.0", path.Root("geo_ip_filtering"), req.Config)...)
|
|
resp.Diagnostics.Append(r.RequireMinVersionForPath("7.0", path.Root("other_timeout"), req.Config)...)
|
|
resp.Diagnostics.Append(r.RequireMinVersionForPath("8.5", path.Root("dns_verification"), req.Config)...)
|
|
resp.Diagnostics.Append(r.RequireMinVersionForPath("9.0", path.Root("unbind_wan_monitors"), req.Config)...)
|
|
}
|