Skip to content

Commit 4da8e68

Browse files
Merge pull request #4853 from openshift-cherrypick-robot/cherry-pick-4824-to-release-4.16
[release-4.16] OCPBUGS-50862: Auto-recover from MC with invalid extension
2 parents 555650f + 7ed831c commit 4da8e68

File tree

4 files changed

+81
-35
lines changed

4 files changed

+81
-35
lines changed

pkg/controller/common/helpers.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,9 +603,50 @@ func ValidateMachineConfig(cfg mcfgv1.MachineConfigSpec) error {
603603
return err
604604
}
605605
}
606+
607+
// Validate MC extensions are in allowlist
608+
if len(cfg.Extensions) > 0 {
609+
if err := ValidateMachineConfigExtensions(cfg); err != nil {
610+
return err
611+
}
612+
}
613+
return nil
614+
}
615+
616+
// Validates that a given MachineConfig's extensions are supported.
617+
func ValidateMachineConfigExtensions(cfg mcfgv1.MachineConfigSpec) error {
618+
return validateExtensions(cfg.Extensions)
619+
}
620+
func validateExtensions(exts []string) error {
621+
supportedExtensions := SupportedExtensions()
622+
invalidExts := []string{}
623+
for _, ext := range exts {
624+
if _, ok := supportedExtensions[ext]; !ok {
625+
invalidExts = append(invalidExts, ext)
626+
}
627+
}
628+
if len(invalidExts) != 0 {
629+
return fmt.Errorf("invalid extensions found: %v", invalidExts)
630+
}
606631
return nil
607632
}
608633

634+
// Returns list of extensions possible to install on a CoreOS based system.
635+
func SupportedExtensions() map[string][]string {
636+
// In future when list of extensions grow, it will make
637+
// more sense to populate it in a dynamic way.
638+
// These are RHCOS supported extensions.
639+
// Each extension keeps a list of packages required to get enabled on host.
640+
return map[string][]string{
641+
"wasm": {"crun-wasm"},
642+
"ipsec": {"NetworkManager-libreswan", "libreswan"},
643+
"usbguard": {"usbguard"},
644+
"kerberos": {"krb5-workstation", "libkadm5"},
645+
"kernel-devel": {"kernel-devel", "kernel-headers"},
646+
"sandboxed-containers": {"kata-containers"},
647+
}
648+
}
649+
609650
// IgnParseWrapper parses rawIgn for both V2 and V3 ignition configs and returns
610651
// a V2 or V3 Config or an error. This wrapper is necessary since V2 and V3 use different parsers.
611652
func IgnParseWrapper(rawIgn []byte) (interface{}, error) {

pkg/controller/common/helpers_test.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -793,3 +793,40 @@ func TestParseAndConvertGzippedConfig(t *testing.T) {
793793
})
794794
}
795795
}
796+
797+
func TestValidateMachineConfigExtensions(t *testing.T) {
798+
t.Parallel()
799+
testCases := []struct {
800+
name string
801+
extensions []string
802+
errExpected bool
803+
}{
804+
{
805+
name: "Supported",
806+
extensions: []string{"kerberos", "sandboxed-containers"},
807+
},
808+
{
809+
name: "Unsupported",
810+
extensions: []string{"unsupported1", "unsupported2"},
811+
errExpected: true,
812+
},
813+
}
814+
for _, testCase := range testCases {
815+
testCase := testCase
816+
t.Run(testCase.name, func(t *testing.T) {
817+
t.Parallel()
818+
mcfgSpec := mcfgv1.MachineConfigSpec{
819+
Extensions: testCase.extensions,
820+
}
821+
err := ValidateMachineConfigExtensions(mcfgSpec)
822+
if testCase.errExpected {
823+
assert.Error(t, err)
824+
for _, ext := range testCase.extensions {
825+
assert.Contains(t, err.Error(), ext)
826+
}
827+
} else {
828+
assert.NoError(t, err)
829+
}
830+
})
831+
}
832+
}

pkg/daemon/daemon.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2850,7 +2850,7 @@ func (dn *Daemon) getUnsupportedPackages() {
28502850
}
28512851

28522852
supportedPackages := make(map[string]bool)
2853-
for _, packages := range getSupportedExtensions() {
2853+
for _, packages := range ctrlcommon.SupportedExtensions() {
28542854
for _, pkg := range packages {
28552855
supportedPackages[pkg] = true
28562856
}

pkg/daemon/update.go

Lines changed: 2 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1674,7 +1674,7 @@ func (dn *Daemon) generateExtensionsArgs(oldConfig, newConfig *mcfgv1.MachineCon
16741674
extArgs := []string{"update"}
16751675

16761676
if dn.os.IsEL() {
1677-
extensions := getSupportedExtensions()
1677+
extensions := ctrlcommon.SupportedExtensions()
16781678
for _, ext := range added {
16791679
for _, pkg := range extensions[ext] {
16801680
extArgs = append(extArgs, "--install", pkg)
@@ -1704,38 +1704,6 @@ func (dn *Daemon) generateExtensionsArgs(oldConfig, newConfig *mcfgv1.MachineCon
17041704
return extArgs
17051705
}
17061706

1707-
// Returns list of extensions possible to install on a CoreOS based system.
1708-
func getSupportedExtensions() map[string][]string {
1709-
// In future when list of extensions grow, it will make
1710-
// more sense to populate it in a dynamic way.
1711-
1712-
// These are RHCOS supported extensions.
1713-
// Each extension keeps a list of packages required to get enabled on host.
1714-
return map[string][]string{
1715-
"wasm": {"crun-wasm"},
1716-
"ipsec": {"NetworkManager-libreswan", "libreswan"},
1717-
"usbguard": {"usbguard"},
1718-
"kerberos": {"krb5-workstation", "libkadm5"},
1719-
"kernel-devel": {"kernel-devel", "kernel-headers"},
1720-
"sandboxed-containers": {"kata-containers"},
1721-
}
1722-
}
1723-
1724-
func validateExtensions(exts []string) error {
1725-
supportedExtensions := getSupportedExtensions()
1726-
invalidExts := []string{}
1727-
for _, ext := range exts {
1728-
if _, ok := supportedExtensions[ext]; !ok {
1729-
invalidExts = append(invalidExts, ext)
1730-
}
1731-
}
1732-
if len(invalidExts) != 0 {
1733-
return fmt.Errorf("invalid extensions found: %v", invalidExts)
1734-
}
1735-
return nil
1736-
1737-
}
1738-
17391707
func (dn *CoreOSDaemon) applyExtensions(oldConfig, newConfig *mcfgv1.MachineConfig) error {
17401708
extensionsEmpty := len(oldConfig.Spec.Extensions) == 0 && len(newConfig.Spec.Extensions) == 0
17411709
if (extensionsEmpty) ||
@@ -1744,7 +1712,7 @@ func (dn *CoreOSDaemon) applyExtensions(oldConfig, newConfig *mcfgv1.MachineConf
17441712
}
17451713

17461714
// Validate extensions allowlist on RHCOS nodes
1747-
if err := validateExtensions(newConfig.Spec.Extensions); err != nil && dn.os.IsEL() {
1715+
if err := ctrlcommon.ValidateMachineConfigExtensions(newConfig.Spec); err != nil && dn.os.IsEL() {
17481716
return err
17491717
}
17501718

0 commit comments

Comments
 (0)