From f0005b852b69b0939fdad78b91d4ea48762c3705 Mon Sep 17 00:00:00 2001 From: Nicolas Perron Date: Wed, 21 Aug 2013 15:58:26 +0200 Subject: [PATCH 1/2] Fixes #3858 - Add possibility to set SUID and SGID for Download a file from a shared folder --- .../1.4/copyFileFromSharedFolder.st | 150 ++++++++++++++++ .../copyGitFile/1.4/metadata.xml | 169 ++++++++++++++++++ 2 files changed, 319 insertions(+) create mode 100644 techniques/fileDistribution/copyGitFile/1.4/copyFileFromSharedFolder.st create mode 100644 techniques/fileDistribution/copyGitFile/1.4/metadata.xml diff --git a/techniques/fileDistribution/copyGitFile/1.4/copyFileFromSharedFolder.st b/techniques/fileDistribution/copyGitFile/1.4/copyFileFromSharedFolder.st new file mode 100644 index 000000000..2ca2ad554 --- /dev/null +++ b/techniques/fileDistribution/copyGitFile/1.4/copyFileFromSharedFolder.st @@ -0,0 +1,150 @@ +##################################################################################### +# Copyright 2011 Normation SAS +##################################################################################### +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +##################################################################################### + + +bundle agent download_from_shared_folder +{ + + vars: + + ©FILE_NAME:{name |"copyfile[&i&][name]" string => "&name&"; +}& + + ©FILE_RECURSION:{rec |"copyfile[&i&][recursion]" string => "&rec&"; +}& + + ©FILE_OWNER:{owner |"copyfile[&i&][owner]" string => "&owner&"; +}& + + ©FILE_GROUP:{group |"copyfile[&i&][group]" string => "&group&"; +}& + + ©FILE_COMPARE_METHOD:{compare_method |"copyfile[&i&][compare_method]" string => "&compare_method&"; +}& + + ©FILE_PERM:{perms |"copyfile[&i&][perm]" string => "&perms&"; +}& + + ©FILE_DESTINATION:{destination |"copyfile[&i&][destination]" string => "&destination&"; +}& + + ©FILE_POST_HOOK_COMMAND:{command |"copyfile[&i&][posthook]" string => "&command&"; +}& + + &TRACKINGKEY:{piuuid |"copyfile[&i&][uuid]" string => "&piuuid&"; +}& + "shared_folder" string => "&SHARED_FILES_FOLDER&"; + + "index" slist => getindices("copyfile"); + + iteration_1:: + "extended_modes_${index}" + string => "4", + ifvarclass => "enable_suid_${index}.!enable_sgid_${index}"; + + "extended_modes_${index}" + string => "2", + ifvarclass => "!enable_suid_${index}.enable_sgid_${index}"; + + "extended_modes_${index}" + string => "6", + ifvarclass => "enable_suid_${index}.enable_sgid_${index}"; + + "extended_modes_${index}" + string => "0", + ifvarclass => "!enable_suid_${index}.!enable_sgid_${index}"; + + classes: + "is_valid" not => strcmp("&SHARED_FILES_FOLDER&", ""); + + "is_file_${index}" not => isdir("${copyfile[${index}][destination]}"); + "exist_${index}" expression => fileexists("${copyfile[${index}][destination]}"); + + ©FILE_SUID:{suid |"enable_suid_&i&" expression => strcmp("&suid&", "true"); +}& + ©FILE_SGID:{sgid |"enable_sgid_&i&" expression => strcmp("&sgid&", "true"); +}& + # Set a class to define when we need to run the post-modification hook + ©FILE_POST_HOOK_RUN:{run |"execute_command_&i&" expression => strcmp("&run&", "true"); +}& + + "iteration_2" expression => "iteration_1"; + "iteration_1" expression => "any"; + + + files: + is_valid.iteration_2:: + + "${copyfile[${index}][destination]}" + copy_from => scp("&SHARED_FILES_FOLDER&/${copyfile[${index}][name]}", "${server_info.cfserved}", "${copyfile[${index}][compare_method]}", "false", "false", "false"), + depth_search => recurse("${copyfile[${index}][recursion]}"), + perms => mog("${copyfile[${index}][perm]}" + , "${copyfile[${index}][owner]}" + , "${copyfile[${index}][group]}"), + comment => "Enforce content of ${copyfile[${index}][destination]} based on the content on the Rudder server with ${copyfile[${index}][compare_method]} method", + classes => kept_if_else("copy_file_${index}_kept", "copy_file_${index}_modified", "copy_file_${index}_failed"), + ifvarclass => "!exist_${index}|!is_file_${index}"; + + # If it's a file, the depth_search prevents from enforcing the file content + # Besides it is possible to specify suid or sgid only for a file + "${copyfile[${index}][destination]}" + copy_from => scp("&SHARED_FILES_FOLDER&/${copyfile[${index}][name]}", "${server_info.cfserved}", "${copyfile[${index}][compare_method]}", "false", "false", "false"), + perms => mog("${extended_modes_${index}}${copyfile[${index}][perm]}" + , "${copyfile[${index}][owner]}" + , "${copyfile[${index}][group]}"), + comment => "Enforce content of file ${copyfile[${index}][destination]} based on the content on the Rudder server with ${copyfile[${index}][compare_method]} method", + classes => kept_if_else("copy_file_${index}_kept", "copy_file_${index}_modified", "copy_file_${index}_failed"), + ifvarclass => "exist_${index}.is_file_${index}"; + + commands: + "${copyfile[${index}][posthook]}" + contain => in_shell, + classes => if_else("copyfile_posthook_${index}_command_run_ok", "copyfile_posthook_${index}_command_run_failed"), + ifvarclass => "execute_command_${index}.copy_file_${index}_modified.!copy_file_${index}_failed", + comment => "Execute the posthook command if a file was changed"; + + reports: + !is_valid:: + "@@copyFile@@result_error@@${copyfile[${index}][uuid]}@@Copy file@@${copyfile[${index}][name]}@@${g.execRun}##${g.uuid}@#There is no shared folder on the Rudder Server, so it's not possible to copy a file from it"; + linux|windows:: + "@@copyFile@@result_success@@${copyfile[${index}][uuid]}@@Copy file@@${copyfile[${index}][name]}@@${g.execRun}##${g.uuid}@#The content of the file(s) is valid" + ifvarclass => "copy_file_${index}_kept.!copy_file_${index}_modified.!copy_file_$(index)_failed"; + + "@@copyFile@@result_repaired@@${copyfile[${index}][uuid]}@@Copy file@@${copyfile[${index}][name]}@@${g.execRun}##${g.uuid}@#The content or permissions of the file(s) has been repaired" + ifvarclass => "copy_file_${index}_modified.!copy_file_$(index)_failed"; + + "@@copyFile@@result_error@@${copyfile[${index}][uuid]}@@Copy file@@${copyfile[${index}][name]}@@${g.execRun}##${g.uuid}@#The content or permissions of the file(s) could not have been repaired for some reason" + ifvarclass => "copy_file_${index}_failed"; + + #posthook reports + "@@copyFile@@result_success@@${copyfile[${index}][uuid]}@@Post-modification hook@@${copyfile[${index}][name]}@@${g.execRun}##${g.uuid}@#No post-hook command for ${copyfile[${index}][destination]} was defined, not executing" + ifvarclass => "!execute_command_${index}"; + + "@@copyFile@@result_success@@${copyfile[${index}][uuid]}@@Post-modification hook@@${copyfile[${index}][name]}@@${g.execRun}##${g.uuid}@#${copyfile[${index}][destination]} was already in the desired state, so no command was executed" + ifvarclass => "execute_command_${index}.copy_file_${index}_kept.!copy_file_${index}_modified"; + + "@@copyFile@@result_success@@${copyfile[${index}][uuid]}@@Post-modification hook@@${copyfile[${index}][name]}@@${g.execRun}##${g.uuid}@#The post-hook command for ${copyfile[${index}][destination]} was correctly executed" + ifvarclass => "copyfile_posthook_${index}_command_run_ok"; + + "@@copyFile@@result_error@@${copyfile[${index}][uuid]}@@Post-modification hook@@${copyfile[${index}][name]}@@${g.execRun}##${g.uuid}@#The post-hook command for ${copyfile[${index}][destination]} couldn't be executed" + ifvarclass => "copyfile_posthook_${index}_command_run_failed"; + + # A copy_from + perms could result in any combinaision of success/repaired/failed, so we have to cover the failed.modified which results in no copy + "@@copyFile@@result_error@@$(copyfile[$(index)][uuid])@@Post-modification hook@@$(copyfile[$(index)][name])@@$(g.execRun)##$(g.uuid)@#$(copyfile[$(index)][destination]) couldn't be copied, so the post-hook command is not executed" + ifvarclass => "execute_command_$(index).copy_file_$(index)_failed"; +} diff --git a/techniques/fileDistribution/copyGitFile/1.4/metadata.xml b/techniques/fileDistribution/copyGitFile/1.4/metadata.xml new file mode 100644 index 000000000..7f21c2999 --- /dev/null +++ b/techniques/fileDistribution/copyGitFile/1.4/metadata.xml @@ -0,0 +1,169 @@ + + + + This technique ensure that some files are the copy of files on the shared folder of the Rudder Root Server, and let you optionally execute a command if the content of the file was modified + + true + + Debian + RHEL / CentOS + SuSE LES / DES / OpenSuSE + cfengine-community + + + + download_from_shared_folder + + + + + + + + COPYFILE_NAME + + + + SHARED_FILES_FOLDER + + + +
+
+ + COPYFILE_NAME + Path of the file to be copied + This is the relative path of the file/folder to be copied, on the Rudder policy server + + + COPYFILE_DESTINATION + Destination of the file + This is the absolute path of the file/folder on the managed node + + + COPYFILE_RECURSION + What should be the recursion level of the copy + + 0 + + + + 1 + + + + inf + + + + 0 + + + + COPYFILE_COMPARE_METHOD + File comparison method + This is the method to use for comparison between source and destination files. + - "mtime" copies the file if the modification time of the source file is more recent than that of the promised file. + - "ctime" CFEngine copies the file if the creation time of the source file is more recent than that of the promised file. + - "atime" CFEngine copies the file if the modification time or creation time of the source file is more recent than that of the promised file. If the times are equal, a byte-for-byte comparison is done on the files to determine if it needs to be copied. + - "exists" copies the file if the promised file does not already exist. + - "binary" copies the file if they are both plain files and a byte-for-byte comparison determines that they are different. If both are not plain files, CFEngine reverts to comparing the mtime and ctime of the files. If the source file is on a different machine (i.e., network copy), then hash is used instead to reduce network bandwidth. + - "digest" copies the file if they are both plain files and a MD5 message digest comparison indicates that the files are different. + The "mtime" option is set by default but "digest" is highly recommended for critical files such as shadow. + + mtime + + + + atime + + + + ctime + + + + digest + + + + binary + + + + exists + + + + + + COPYFILE_OWNER + Owner of the file + + root + + + + COPYFILE_GROUP + Group of the file + + root + + + + COPYFILE_PERM + Permissions to apply on the file + + perm + + + + COPYFILE_SUID + Set SetUID bit? + + boolean + + + + COPYFILE_SGID + Set SetGID bit? + Note: The SetUID and SetGID bits will not be applied recursively, for obvious security reasons. + + boolean + + +
+ +
+ + COPYFILE_POST_HOOK_RUN + Should the command(s) below be run if any modifications (permission or overwriting) are made on the files above? + boolean + + + COPYFILE_POST_HOOK_COMMAND + Command to run after any modifications + + textarea + true + + +
+
+
+ +
From b0b0f631b1233267dfb5900f7f45a6120a867f5a Mon Sep 17 00:00:00 2001 From: Nicolas Perron Date: Wed, 28 Aug 2013 10:53:02 +0200 Subject: [PATCH 2/2] Refs #3858 - Reindent and add more informations --- .../1.4/copyFileFromSharedFolder.st | 38 +++++++++++-------- .../copyGitFile/1.4/metadata.xml | 1 + 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/techniques/fileDistribution/copyGitFile/1.4/copyFileFromSharedFolder.st b/techniques/fileDistribution/copyGitFile/1.4/copyFileFromSharedFolder.st index 2ca2ad554..4c7f0ea49 100644 --- a/techniques/fileDistribution/copyGitFile/1.4/copyFileFromSharedFolder.st +++ b/techniques/fileDistribution/copyGitFile/1.4/copyFileFromSharedFolder.st @@ -91,24 +91,30 @@ bundle agent download_from_shared_folder is_valid.iteration_2:: "${copyfile[${index}][destination]}" - copy_from => scp("&SHARED_FILES_FOLDER&/${copyfile[${index}][name]}", "${server_info.cfserved}", "${copyfile[${index}][compare_method]}", "false", "false", "false"), + copy_from => scp("&SHARED_FILES_FOLDER&/${copyfile[${index}][name]}", "${server_info.cfserved}", "${copyfile[${index}][compare_method]}", "false", "false", "false"), depth_search => recurse("${copyfile[${index}][recursion]}"), - perms => mog("${copyfile[${index}][perm]}" - , "${copyfile[${index}][owner]}" - , "${copyfile[${index}][group]}"), - comment => "Enforce content of ${copyfile[${index}][destination]} based on the content on the Rudder server with ${copyfile[${index}][compare_method]} method", - classes => kept_if_else("copy_file_${index}_kept", "copy_file_${index}_modified", "copy_file_${index}_failed"), - ifvarclass => "!exist_${index}|!is_file_${index}"; - - # If it's a file, the depth_search prevents from enforcing the file content - # Besides it is possible to specify suid or sgid only for a file + perms => mog( + "${copyfile[${index}][perm]}", + "${copyfile[${index}][owner]}", + "${copyfile[${index}][group]}" + ), + comment => "Enforce content of ${copyfile[${index}][destination]} based on the content on the Rudder server with ${copyfile[${index}][compare_method]} method", + classes => kept_if_else("copy_file_${index}_kept", "copy_file_${index}_modified", "copy_file_${index}_failed"), + ifvarclass => "!exist_${index}|!is_file_${index}"; + + # If it s a file, the depth_search prevents from enforcing the file content + # Besides it is possible to specify suid or sgid only for a file since this + # is too dangerous to apply suid or sgid recursively and only copy an empty + # directory does not make sense. "${copyfile[${index}][destination]}" - copy_from => scp("&SHARED_FILES_FOLDER&/${copyfile[${index}][name]}", "${server_info.cfserved}", "${copyfile[${index}][compare_method]}", "false", "false", "false"), - perms => mog("${extended_modes_${index}}${copyfile[${index}][perm]}" - , "${copyfile[${index}][owner]}" - , "${copyfile[${index}][group]}"), - comment => "Enforce content of file ${copyfile[${index}][destination]} based on the content on the Rudder server with ${copyfile[${index}][compare_method]} method", - classes => kept_if_else("copy_file_${index}_kept", "copy_file_${index}_modified", "copy_file_${index}_failed"), + copy_from => scp("&SHARED_FILES_FOLDER&/${copyfile[${index}][name]}", "${server_info.cfserved}", "${copyfile[${index}][compare_method]}", "false", "false", "false"), + perms => mog( + "${extended_modes_${index}}${copyfile[${index}][perm]}", + "${copyfile[${index}][owner]}", + "${copyfile[${index}][group]}" + ), + comment => "Enforce content of file ${copyfile[${index}][destination]} based on the content on the Rudder server with ${copyfile[${index}][compare_method]} method", + classes => kept_if_else("copy_file_${index}_kept", "copy_file_${index}_modified", "copy_file_${index}_failed"), ifvarclass => "exist_${index}.is_file_${index}"; commands: diff --git a/techniques/fileDistribution/copyGitFile/1.4/metadata.xml b/techniques/fileDistribution/copyGitFile/1.4/metadata.xml index 7f21c2999..6f51a6033 100644 --- a/techniques/fileDistribution/copyGitFile/1.4/metadata.xml +++ b/techniques/fileDistribution/copyGitFile/1.4/metadata.xml @@ -134,6 +134,7 @@ along with this program. If not, see . COPYFILE_SUID Set SetUID bit? + Note: The SetUID and SetGID bits will not be applied recursively, for obvious security reasons. boolean