diff --git a/data/data/bootstrap/baremetal/files/usr/local/bin/startironic.sh.template b/data/data/bootstrap/baremetal/files/usr/local/bin/startironic.sh.template index 99523089848..be564056864 100755 --- a/data/data/bootstrap/baremetal/files/usr/local/bin/startironic.sh.template +++ b/data/data/bootstrap/baremetal/files/usr/local/bin/startironic.sh.template @@ -94,7 +94,24 @@ for port in 80 5050 6385 ; do fi done +# It is possible machine-api-operator comes up while the bootstrap is +# online, meaning there could be two DHCP servers on the network. To +# avoid bootstrap responding to a worker, which would cause a failed +# deployment, we filter out requests from anyone else than the control +# plane. We are using iptables instead of dnsmasq's dhcp-host because +# DHCPv6 wants to use DUID's instead of mac addresses. +{{if .PlatformData.BareMetal.ProvisioningDHCPAllowList}} +$IPTABLES -t raw -N DHCP +$IPTABLES -t raw -A PREROUTING -p udp --dport 67 -j DHCP +$IPTABLES -t raw -A PREROUTING -p udp --dport 546 -j DHCP + +for mac in {{.PlatformData.BareMetal.ProvisioningDHCPAllowList}} +do + $IPTABLES -t raw -A DHCP -m mac --mac-source "$mac" -j ACCEPT +done +$IPTABLES -t raw -A DHCP -j DROP +{{end}} # Wait for images to be downloaded/ready podman wait -i 1000 ipa-downloader diff --git a/pkg/asset/ignition/bootstrap/baremetal/template.go b/pkg/asset/ignition/bootstrap/baremetal/template.go index 526481e64f0..7a92de1f46f 100644 --- a/pkg/asset/ignition/bootstrap/baremetal/template.go +++ b/pkg/asset/ignition/bootstrap/baremetal/template.go @@ -2,6 +2,7 @@ package baremetal import ( "github.com/openshift/installer/pkg/types/baremetal" + "strings" ) // TemplateData holds data specific to templates used for the baremetal platform. @@ -18,6 +19,10 @@ type TemplateData struct { // ProvisioningDHCPRange has the DHCP range, if DHCP is not external. Otherwise it // should be blank. ProvisioningDHCPRange string + + // ProvisioningDHCPAllowList contains a space-separated list of all of the control plane's boot + // MAC addresses. Requests to bootstrap DHCP from other hosts will be ignored. + ProvisioningDHCPAllowList string } // GetTemplateData returns platform-specific data for bootstrap templates. @@ -33,6 +38,14 @@ func GetTemplateData(config *baremetal.Platform) *TemplateData { if !config.ProvisioningDHCPExternal { templateData.ProvisioningDHCPRange = config.ProvisioningDHCPRange + + var dhcpAllowList []string + for _, host := range config.Hosts { + if host.Role == "master" { + dhcpAllowList = append(dhcpAllowList, host.BootMACAddress) + } + } + templateData.ProvisioningDHCPAllowList = strings.Join(dhcpAllowList, " ") } return &templateData diff --git a/pkg/asset/ignition/bootstrap/baremetal/template_test.go b/pkg/asset/ignition/bootstrap/baremetal/template_test.go index 2e2d837dbb0..016dbb72ce7 100644 --- a/pkg/asset/ignition/bootstrap/baremetal/template_test.go +++ b/pkg/asset/ignition/bootstrap/baremetal/template_test.go @@ -13,6 +13,24 @@ func TestTemplatingIPv4(t *testing.T) { BootstrapProvisioningIP: "172.22.0.2", ProvisioningDHCPExternal: false, ProvisioningDHCPRange: "172.22.0.10,172.22.0.100", + Hosts: []*baremetal.Host{ + { + Role: "master", + BootMACAddress: "c0:ff:ee:ca:fe:00", + }, + { + Role: "master", + BootMACAddress: "c0:ff:ee:ca:fe:01", + }, + { + Role: "master", + BootMACAddress: "c0:ff:ee:ca:fe:02", + }, + { + Role: "worker", + BootMACAddress: "c0:ff:ee:ca:fe:03", + }, + }, } result := GetTemplateData(&bareMetalConfig) @@ -21,6 +39,7 @@ func TestTemplatingIPv4(t *testing.T) { assert.Equal(t, result.ProvisioningCIDR, 24) assert.Equal(t, result.ProvisioningIPv6, false) assert.Equal(t, result.ProvisioningIP, "172.22.0.2") + assert.Equal(t, result.ProvisioningDHCPAllowList, "c0:ff:ee:ca:fe:00 c0:ff:ee:ca:fe:01 c0:ff:ee:ca:fe:02") } func TestTemplatingIPv6(t *testing.T) { @@ -36,4 +55,5 @@ func TestTemplatingIPv6(t *testing.T) { assert.Equal(t, result.ProvisioningCIDR, 64) assert.Equal(t, result.ProvisioningIPv6, true) assert.Equal(t, result.ProvisioningIP, "fd2e:6f44:5dd8:b856::2") + assert.Equal(t, result.ProvisioningDHCPAllowList, "") }