From 612e44d7aa381148e3ac3913dd97970532cdcdf9 Mon Sep 17 00:00:00 2001 From: Colan Schwartz Date: Sun, 26 Aug 2012 01:02:36 -0400 Subject: [PATCH] Issue #990812 by colan: Add "permissions" subcommand to fix ownership/perms. --- commands/perms/perms.drush.inc | 198 ++++++++++++++++++++++++++++++++++++++++ 1 files changed, 198 insertions(+), 0 deletions(-) create mode 100644 commands/perms/perms.drush.inc diff --git a/commands/perms/perms.drush.inc b/commands/perms/perms.drush.inc new file mode 100644 index 0000000..ab7d71d --- /dev/null +++ b/commands/perms/perms.drush.inc @@ -0,0 +1,198 @@ + "Set appropriate ownership and permissions of files and directories within a Drupal web directory.", + 'arguments' => array( + 'user owner' => 'The user that will own the files. For security reasons, it is recommended that this user should be neither "root" (the superuser) nor the web user (e.g. "www-data" or "apache")', + 'group owner' => 'The group that will own the files.', + 'web user' => 'The web user as per your web server configuration that will own and manage files in Drupal\'s file system.', + ), + 'required-arguments' => TRUE, + 'options' => array( + 'docs' => 'Octal permissions for documentation files such as "INSTALL.txt". Optional; default is 0660.', + 'readonly-files' => 'Octal permissions for files that need to be read by (but not written to) the web server such as PHP files. Optional; default is 0664.', + 'readonly-dirs' => 'Octal permissions for directories that need to be read by (but not written to) the web server such as directories containing PHP files. Optional; default is 0775.', + 'settings' => 'Octal permissions for settings.php configuration files. Optional; default is 0664.', + 'fs-files' => 'Octal permissions for Drupal\'s file system files (files in the "files" directory) that need to be readable and writable by the web server. Optional; default is 0664.', + 'fs-dirs' => 'Octal permissions for Drupal\'s file system directories (directories in the "files" directory) that need to be readable and writable by the web server. Optional; default is 0775.', + ), + 'examples' => array( + 'drush permissions alice devs www-data' => 'Set permissions with "alice" as the user owner and "devs" as the group owner. Files in Drupal\'s file system will be owned by the web user "www-data".', + 'drush perms --docs=0660 bob bob apache' => 'Set permissions with "bob" as the user owner and "bob" as the group owner. This will give "bob" exclusive access by setting the group to his primary group. Files in Drupal\'s file system will be owned by the web user "apache". Documentation files will be readable and writable by the user and group, but nobody else.', + ), + 'aliases' => array('perms'), + // Just need the root directory. + 'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_ROOT, + ); + + return $items; +} + +/** + * Implementats hook_drush_help(). + */ +function perms_drush_help($section) { + switch ($section) { + case 'drush:permissions': + return dt("Set appropriate ownership and permissions of files and directories within a Drupal web directory."); + } +} + +/* + * Implementats drush_hook_COMMAND_validate(). + */ +function drush_perms_permissions_validate($owner_user, $owner_group, $owner_fs) { + + // Make sure that we've got a POSIX system. + if (!function_exists('posix_getpwuid')) { + return drush_set_error( + 'ERROR_NON_POSIX', + dt('Currently, this command can only be run on a POSIX system.') + ); + } + + // Make sure that the command is being run as an administrator. + $name = posix_getpwuid(posix_geteuid()); + if ($name['name'] !== 'root') { + return drush_set_error( + 'ERROR_MUST_BE_ROOT', + dt('You must be root to run this command by prefixing it with "sudo".') + ); + } + + // Make sure that the username is valid. + if (!posix_getpwnam($owner_user)) { + return drush_set_error( + 'ERROR_USER_INVALID', + dt('The user owner must be a valid user.') + ); + } + + // Make sure that the group is valid. + if (!posix_getgrnam($owner_group)) { + return drush_set_error( + 'ERROR_GROUP_INVALID', + dt('You must specify a valid group.') + ); + } + + // Make sure that the web user is valid. + if (!posix_getpwnam($owner_fs)) { + return drush_set_error( + 'ERROR_USER_WEB_INVALID', + dt('The web user must be a valid user.') + ); + } +} + +/** + * Implements drush_COMMANDFILE_COMMANDNAME(). + */ +function drush_perms_permissions($owner_user, $owner_group, $owner_fs) { + + // Get the Drupal root. + if (!$drupal_root = drush_get_context('DRUSH_DRUPAL_ROOT')) { + return drush_set_error( + 'ERROR_CANNOT_GET_ROOT', + dt('Cannot determine the Drupal root directory.') + ); + } + + // Create an iteration of files starting at the Drupal root. + $iterator = new RecursiveIteratorIterator( + new RecursiveDirectoryIterator( + $drupal_root, + RecursiveDirectoryIterator::FOLLOW_SYMLINKS + ), + RecursiveIteratorIterator::SELF_FIRST + ); + + // Iterate through all of the files. + foreach ($iterator as $current_file) { + + // If a group was provided, set it as the group owner. + if ($owner_group) { + chgrp($current_file->getPathname(), $owner_group); + } + + // Determine class (readability and writability) of the file or directory. + if (preg_match('/^[A-Z]+\.([a-z]+\.)?txt$/', $current_file->getFilename())) { + + /* + * This file is purely documentation for system adminstrators. It should + * not be read or written by the web server. + */ + + // Set proper ownership and permissions. + chown($current_file->getPathname(), $owner_user); + chmod($current_file->getPathname(), octdec(drush_get_option('docs', '0660'))); + } + + else if ($current_file->getFilename() == 'settings.php') { + + /* + * This is a settings.php file. These are special because the web server + * needs to be able to read it, but it shouldn't be read by anyone else + * as it contains password information. + */ + + // Set proper ownership and permissions. + chown($current_file->getPathname(), $owner_user); + chmod($current_file->getPathname(), octdec(drush_get_option('settings', '0664'))); + } + else if (preg_match('/\/sites\/.*\/files($|\/)/', $current_file->getPathname())) { + + /* + * This file or directory is part of Drupal's file system for uploaded + * files. It needs to be readable and writable by the web server. + */ + + // Set proper ownership. + chown($current_file->getPathname(), $owner_fs); + + // Set proper permissions. + if ($iterator->isFile()) { + chmod($current_file->getPathname(), octdec(drush_get_option('fs-files', '0664'))); + } + else if ($iterator->isDir()) { + chmod($current_file->getPathname(), octdec(drush_get_option('fs-dirs', '0775'))); + } + } + else { + + /* + * All remaining files and directories are readable, but not writable. + * It is theoretically possible for things to be writable and not + * readable, but there's no reason for this to ever happen on a Drupal + * site. + */ + + // Set the appropriate user owner. + chown($current_file->getPathname(), $owner_user); + + // Set the appropriate permissions. + if ($iterator->isFile()) { + chmod($current_file->getPathname(), octdec(drush_get_option('readonly-files', '0664'))); + } + else if ($iterator->isDir()) { + chmod($current_file->getPathname(), octdec(drush_get_option('readonly-dirs', '0775'))); + } + } + } +} + -- 1.7.0.4