diff --git a/internal/blueprint/fsnode_customizations.go b/internal/blueprint/fsnode_customizations.go index 92ba2f676..cce499641 100644 --- a/internal/blueprint/fsnode_customizations.go +++ b/internal/blueprint/fsnode_customizations.go @@ -12,6 +12,7 @@ import ( "github.com/osbuild/osbuild-composer/internal/common" "github.com/osbuild/osbuild-composer/internal/fsnode" + "github.com/osbuild/osbuild-composer/internal/pathpolicy" ) // validateModeString checks that the given string is a valid mode octal number @@ -434,3 +435,37 @@ func ValidateDirFileCustomizations(dirs []DirectoryCustomization, files []FileCu return nil } + +// CheckFileCustomizationsPolicy checks if the given File customizations are allowed by the path policy. +// If any of the customizations are not allowed by the path policy, an error is returned. Otherwise, nil is returned. +func CheckFileCustomizationsPolicy(files []FileCustomization, pathPolicy *pathpolicy.PathPolicies) error { + var invalidPaths []string + for _, file := range files { + if err := pathPolicy.Check(file.Path); err != nil { + invalidPaths = append(invalidPaths, file.Path) + } + } + + if len(invalidPaths) > 0 { + return fmt.Errorf("the following custom files are not allowed: %+q", invalidPaths) + } + + return nil +} + +// CheckDirectoryCustomizationsPolicy checks if the given Directory customizations are allowed by the path policy. +// If any of the customizations are not allowed by the path policy, an error is returned. Otherwise, nil is returned. +func CheckDirectoryCustomizationsPolicy(dirs []DirectoryCustomization, pathPolicy *pathpolicy.PathPolicies) error { + var invalidPaths []string + for _, dir := range dirs { + if err := pathPolicy.Check(dir.Path); err != nil { + invalidPaths = append(invalidPaths, dir.Path) + } + } + + if len(invalidPaths) > 0 { + return fmt.Errorf("the following custom directories are not allowed: %+q", invalidPaths) + } + + return nil +} diff --git a/internal/blueprint/fsnode_customizations_test.go b/internal/blueprint/fsnode_customizations_test.go index 1f25730ab..22d66023d 100644 --- a/internal/blueprint/fsnode_customizations_test.go +++ b/internal/blueprint/fsnode_customizations_test.go @@ -8,6 +8,7 @@ import ( "github.com/BurntSushi/toml" "github.com/osbuild/osbuild-composer/internal/common" "github.com/osbuild/osbuild-composer/internal/fsnode" + "github.com/osbuild/osbuild-composer/internal/pathpolicy" "github.com/stretchr/testify/assert" ) @@ -1132,3 +1133,122 @@ func TestValidateDirFileCustomizations(t *testing.T) { }) } } + +func TestCheckFileCustomizationsPolicy(t *testing.T) { + policy := map[string]pathpolicy.PathPolicy{ + "/": {Deny: true}, + "/etc": {}, + "/etc/fstab": {Deny: true}, + "/etc/os-release": {Deny: true}, + "/etc/hostname": {Deny: true}, + "/etc/shadow": {Deny: true}, + "/etc/passwd": {Deny: true}, + "/etc/group": {Deny: true}, + } + pathPolicy := pathpolicy.NewPathPolicies(policy) + + testCases := []struct { + Name string + Files []FileCustomization + Error bool + }{ + { + Name: "disallowed-file", + Files: []FileCustomization{ + { + Path: "/etc/shadow", + }, + }, + Error: true, + }, + { + Name: "disallowed-file-2", + Files: []FileCustomization{ + { + Path: "/home/user/.ssh/authorized_keys", + }, + }, + Error: true, + }, + { + Name: "disallowed-file-3", + Files: []FileCustomization{ + { + Path: "/file", + }, + }, + Error: true, + }, + { + Name: "allowed-file-named", + Files: []FileCustomization{ + { + Path: "/etc/named.conf", + }, + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.Name, func(t *testing.T) { + err := CheckFileCustomizationsPolicy(tc.Files, pathPolicy) + if tc.Error { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + }) + } +} + +func TestCheckDirectoryCustomizationsPolicy(t *testing.T) { + policy := map[string]pathpolicy.PathPolicy{ + "/": {Deny: true}, + "/etc": {}, + } + pathPolicy := pathpolicy.NewPathPolicies(policy) + + testCases := []struct { + Name string + Directories []DirectoryCustomization + Error bool + }{ + { + Name: "disallowed-directory", + Directories: []DirectoryCustomization{ + { + Path: "/dir", + }, + }, + Error: true, + }, + { + Name: "disallowed-directory-2", + Directories: []DirectoryCustomization{ + { + Path: "/var/log/fancy-dir", + }, + }, + Error: true, + }, + { + Name: "allowed-directory", + Directories: []DirectoryCustomization{ + { + Path: "/etc/systemd/system/sshd.service.d", + }, + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.Name, func(t *testing.T) { + err := CheckDirectoryCustomizationsPolicy(tc.Directories, pathPolicy) + if tc.Error { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + }) + } +}