Most of the issues I see that block tasks from running successfully are caused by permissions problems. More often than not, these are files written by Drupal (or CiviCRM) with mode 0600, owned by the web user. 'aegir', despite being a member of the web group (i.e. www-data) is not in a position to operate on such files. The resolution is usually to chown and chmod these files as root.

In other issues, we've discussed adding a script that could be called under sudo to perform such fixes securely. Of course this is the tricky part. We'd need to ensure that the command was only ever run against site directories, and wouldn't permit arbitrary chmod()ing and chown()ing.

I think we could accomplish this with a Drush command (or three), which would have the added benefit of making it reasonably simple to wrap it in an Aegir task. If we're running the script under sudo, then it will be executed as root, so we'll need to point it to our aliases/contexts. We could try using the --include option (and maybe also --local) to make all and only aliases in /var/aegir/.drush available.

I think this might look like:

  1. A sudo entry is manually created upon installing this command and would look like:
    aegir ALL=NOPASSWD: /usr/local/bin/drush fix-permissions /var/aegir/.drush /var/aegir/platforms
    Which hardcodes both the alias include path and a 'jail' dir as arguments.
  2. Aegir calls drush @example.com provision-fix-permissions.
  3. provision-fix-permissions invokes sudo drush fix-permissions /var/aegir/.drush /var/aegir/platforms @example.com.
  4. drush fix-permissions then calls drush --include=/var/aegir/.drush --jail=/var/aegir/platforms @example fix-permissions-real.
  5. drush fix-permissions-real looks for a --site-path option, validates that the path is under /var/aegir/platforms, and only then operate its chown()s and chmod()s.

We might want to include such commands under hosting_tasks_extra or hosting_dev.

CommentFileSizeAuthor
#6 add_fix_permissions-2616426-5.patch3.31 KBhelmo
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

ergonlogic created an issue. See original summary.

ergonlogic’s picture

Issue summary: View changes
gboudrias’s picture

Solid plan. I was planning on making this a separate module but it seems that this is more or less what tasks_extra is for.

helmo’s picture

+1 for creating such a script/task.

One downside of using drush for this is the risk of priviledge escalation.

If the fix-permissions drush command is called as root, can we be sure that no other code where the aegir user can write to is used?
In most current installations the aegir user can modify the drush code ... or add a drush module with e.g. a pre hook.

So any code called via sudo should be only writable by root. My vote would be for a compact standalone script php of shell without any includes.

What about the script from #1737266: The directory sites/drupal7.d7.local/files is not writable.

helmo’s picture

I've taken the script example from https://www.drupal.org/node/244924, and opened a pull request in one of the git repo's tracking it.

Instructions:
Copy the fix-permissions.sh script from this patch to /usr/local/bin/fix-permissions.sh (especially a place where the aegir user should have NO write access).

Add to sudo with `visudo -f /etc/sudoers.d/aegir`

aegir ALL = (root) NOPASSWD: /usr/local/bin/fix-permissions.sh

Usage:
sudo /usr/local/bin/fix-permissions.sh --drupal_path=/var/aegir/platforms/drupal-8.0.x --drupal_user=aegir

About adding a task ... this script works on a platform ... so a platform task would make the most sense.

We could eventually include this in the Debian package install but only after thorough review.

helmo’s picture

Status: Active » Needs review
FileSize
3.31 KB
helmo’s picture

A slightly more specific sudo line:
aegir ALL = (root) NOPASSWD: /usr/local/bin/fix-drupal-file-permissions.sh --drupal_path=/var/aegir/platforms/*/ --drupal_user=aegir

And I suggest to name the script fix-drupal-file-permissions.sh to make it's purpose even more explicit.

clemens.tolboom’s picture

I assumed the verify task was for fixing permissions too. What is wrong with that?

If we need a script (jikes) for that I agree with @helmo to name it fix-drupal-file-permissions

(a hostmaster user)

clemens.tolboom’s picture

I was talking about site file permissions. My site was broken as site verify seemed to fix top level files dir(s) but forgot it's children

Why not ask the site for it's private:// public:// and temp:// and fix those recursive?

helmo’s picture

Status: Needs review » Needs work

private/temp needs to be handled.

And I think we can simplify it to only work on sites ... not the platform.

helmo’s picture

Issue tags: +Aegir 3.4

targeting for the next release

gboudrias’s picture

Issue tags: -Aegir 3.4
Jon Pugh’s picture

Priority: Normal » Major

Marking major. This is a sleeping dragon of a problem, one that most people aren't aware of, and one that causes aegir to "look bad".

helmo’s picture

Jon Pugh’s picture

After a comment from omega8cc, I think this needs to be a part of aegir core's Verify task.

We already are setting permissions on files as much as aegir user is allowed. In fact this is one of the big selling points of aegir: "You don't have to mess with file permissions." ...

I would almost call this a bug. When the system claims to "set permissions, configuration, and ensure the site is in order" but it actually can't properly reset permissions on uploaded files, wouldn't that be a bug?

Let's make this happen...

memtkmcc’s picture

In BOA we are running global permissions fix daily, for all sites (but also for custom platforms, to make sure people don't try to make their codebases writable in some dangerous way). It helps a bit, but is still not ideal, since once you clone a site, you can't wait until the next day to have all permissions fixed for you. It should be fixed on the fly. Here is the script we run daily. It does many more than permissions fix, and already turned into spaghetti code, so we need to make it modular, but maybe parts of it could offer some hints.

The procedure where the global fix happens, can be seen here: fix_permissions()

memtkmcc’s picture

Please note that the fix should be run (available as an extra task?) both for sites and platforms.

It is otherwise possible that people create codebase which is not writable by the Aegir user, and it will instead log warnings like:

Could not change permissions of /path/to/platform/sites/all to 755 (chmod to 755 failed on /path/to/platform/sites/all)
Could not change permissions of /path/to/platform/sites to 751 (chmod to 751 failed on /path/to/platform/sites)
ergonlogic’s picture

I agree that we need to be able to fix both sites and platforms, but I'd prefer that we do it under separate scripts and tasks. That is, have both a fix-drupal-platform-permissions.sh and a fix-drupal-site-permissions.sh, called by the respective "verify" tasks.

This could be added as a feature to tasks_extra, so that it remains optional, and could be implemented in a pre-verify hook.

ergonlogic’s picture

I've added a prototype implementation in the dev/fix-permissions branch of hosting_tasks_extra: http://cgit.drupalcode.org/hosting_tasks_extra/tree/fix_permissions?h=de...

There's an install.sh script to deploy the fix-permissions.sh script (copied from https://www.drupal.org/node/244924), setting up sudoers, etc. Then we have the Hosting Feature scaffolding that allows the functionality to bel enabled from the front-end. Finally, there's a basic drush_hook_pre_provision_verify(), where we call the script, passing in the relevant arguments, and log the results. It will currently only run on platform verify tasks.

Next steps should probably include:

  • adding error checking
  • splitting fix-permissions.sh into platform- and site-specific scripts;
  • switch to the same option names we already use in Provision

We may also need to add a Drush command, which would more easily allow for remote execution. We'd then also need to ensure that we're deploying the scripts, sudoers entry, etc. to web nodes. It'd also just be a nice convenience feature to be able to run: drush @example.com fix-permissions

colan’s picture

We may also need to add a Drush command, which would more easily allow for remote execution.

In case anyone's interested in looking at the code, I worked on a Drush command for fixing permissions a while ago which never got committed. The issue is #990812: Add a "permissions" subcommand to fix/set all file permissions.

Edit: The most recent patch is probably the most useful: https://www.drupal.org/node/990812#comment-7013970.

ergonlogic’s picture

Thanks for sharing that, @colan. That's a long issue thread, so I only skimmed it. Feel free to point out any specifics that you might think are relevant here.

FWIW, we started out looking at doing this in Drush, but @helmo's concerns in comment #4 shifted the focus to a stand-alone shell script. Also, Aegir already attempts to fix ownership and permissions in _provision_drupal_create_directories(). It's in-ability to chown and chgrp effectively is the main motivation for this script, as it'll need to be run under sudo.

It occurs to me, having just re-stated it above, that the permissions changes in the script are redundant with those in Aegir core, and don't actually match, in some cases. I wonder if this script could be trimmed down to just the chown and chgrp, as that should allow Aegir's native permissions handling to work.

ergonlogic’s picture

Status: Needs work » Needs review

I've now split out fixing ownership from permissions, as well as site operations from platform ones, to allow for more granular testing and experimentation. I also added better error-checking and logging, as well as switching to the native Aegir option names (i.e., "root", "script-user", etc.)

I think these additions are ready for review and testing, so long as sites are hosted locally. I suspect that support for remote servers will require a separate Drush wrapper in order to work smoothly. While our hub & spoke model ought to sync these changes out to remotes, in some cases the remote is authoritative, and so this might not apply.

ergonlogic’s picture

I've implemented a couple hooks in these new extensions to disable Aegir core's chgrp and chmod, since it was ending up flipping some perms back and forth.

helmo’s picture

What about the 'sites/example.com/private' I assume that needs the same commands as used for files.

ergonlogic’s picture

Added fixes to private/ perms in 87cf4fd (dev/fix-permissions branch of hosting_tasks_extra)

This results in .htaccess files under private being chmod'd 660. Should www-data be able to write to .htaccess? I guess since we don't use them anyway, it's a moot point...

ergonlogic’s picture

Running this in a pre-verify hook can be insufficient to leave a properly working site. For example, CiviCRM will delete and recreate some directories during its cache-clear, that occurs late in a post-verify hook. So, moving to a post-hook, and renaming the Drush files and hook implementations to add a "zz_" prefix, are sufficient to ensure our script is run last. Kind of ugly though, so I haven't committed it yet.

I had experimented with mechanisms to re-order Drush hooks, but I don't think they were ever merged. Does anyone know a better way to achieve this?

helmo’s picture

Hook re-ordering would be nice here ... but would also make it even more complex. The zz_ prefix seems like an easy solution. Otherwise we might have to look for another hook... a post_post hook :) ?

colan’s picture

Module weights?

ergonlogic’s picture

I've pushed the change to prepend "zz_".

Unfortunately, Drush doesn't have a concept of module weights, unless that's changes in the last year or so. It relies only on the alphabetical order of the extensions/commandfiles.

We might want to add a couple hooks within our hook implementations, to avoid other contrib having to be named "zzz_...". In fact, we could split out the "zz_" implementations into a stand-alone extension (still within hosting_tasks_extra), that simply provides a convenient way to provide something like "post_post" hooks (maybe "post_final"). Anyway, we can table that discussion, unless and until someone cares enough to start a new issue about it.

colan’s picture

Unfortunately, Drush doesn't have a concept of module weights, unless that's changes in the last year or so. It relies only on the alphabetical order of the extensions/commandfiles.

I just found Allow modules to control the order of hook invocations which you worked on a while ago, but it looks like it may require the listed follow-up? It would be good to get that in.

ergonlogic’s picture

Right, this failing PR is probably a good start: https://github.com/drush-ops/drush/pull/462. That said, it's really outside the scope of this issue, since the "zz_" solution works, and should be pretty easily re-factored in a hook invocation order altering hook is merged into Drush.

As far as fixing file ownership and permissions, I think we're in pretty good shape. The only remaining item, as far as I can tell, is the concern I raised in #19. That is, execution of these scripts on platforms and sites that live on remote servers.

Assuming we're otherwise good here, I'd like to merge the dev/fix-permissions branch, and work on any fixes required for remote execution in a new issue. Any objections?

Jon Pugh’s picture

Running this in a pre-verify hook can be insufficient to leave a properly working site. For example, CiviCRM will delete and recreate some directories during its cache-clear, that occurs late in a post-verify hook. So, moving to a post-hook, and renaming the Drush files and hook implementations to add a "zz_" prefix, are sufficient to ensure our script is run last. Kind of ugly though, so I haven't committed it yet.

That's a really good point, update hooks or drupal cache clearing might do things to files too.

But I'm thinking we might actually need to run this both pre and post verify.

I run into the situation where Aegir verify cannot run because some file is unwritable, so the fixperms would need to be fixed before that.

helmo’s picture

This needs a good hint to the user that the install script needs to be executed ... for both permission and ownership modules.
If you currently fail do to do this you get a warning in the task log which is not directly obvious.

helmo’s picture

Status: Needs review » Reviewed & tested by the community

I've added a drupal_set_message when the modules are enabled...

Bonus points lets it link to the actual docs... but rtbc otherwise

Jon Pugh’s picture

Perhaps implementing a "hook_requirements()" would be helpful, not just for this but other things Aegir needs?

helmo’s picture

Project: Hostmaster (Aegir) » Aegir Hosting Tasks Extra
Status: Reviewed & tested by the community » Fixed
helmo’s picture

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

inteja’s picture

I'm running Aegir 3.9 and have enabled the Fix Permissions and Fix Ownership modules and run the bash install scripts but verify is now throwing warning for sites that previously verified.

EDIT:

I see in the Aegir log for one verify task:

Calling hook drush_zz_fix_ownership_post_provision_verify	
sudo: no tty present and no askpass program specified
inteja’s picture

Worked it out. For whatever reason, running the sudo bash scripts/install.sh in each of these submodules resulted in copying the scripts to /usr/local/bin/ and setting the correct file ownership and permissions, but did not add the corresponding entries to sudoers. So I manually added the following to my sudoers file and now it works as advertised.

aegir ALL=NOPASSWD: /usr/local/bin/fix-drupal-platform-ownership.sh
aegir ALL=NOPASSWD: /usr/local/bin/fix-drupal-site-ownership.sh
aegir ALL=NOPASSWD: /usr/local/bin/fix-drupal-platform-permissions.sh
aegir ALL=NOPASSWD: /usr/local/bin/fix-drupal-site-permissions.sh
ToRum’s picture

We ran into this issue while trying to install Aegir 3.9 manually. Since drush hostmaster-install needs to be run as the aegir user, this user is not allowed to run the hostmaster-7.x-3.9/profiles/hostmaster/modules/aegir/hosting_tasks_extra/fix_ownership/scripts/install.sh and hostmaster-7.x-3.9/profiles/hostmaster/modules/aegir/hosting_tasks_extra/fix_permissions/scripts/install.sh scripts.

As a workaround, we first executed the following commands as root user:

cd /root/
drush dl hostmaster-7.x-3.9
sh /root/hostmaster-7.x-3.9/profiles/hostmaster/modules/aegir/hosting_tasks_extra/fix_ownership/scripts/install.sh
sh /root/hostmaster-7.x-3.9/profiles/hostmaster/modules/aegir/hosting_tasks_extra/fix_permissions/scripts/install.sh
rm -fr /root/hostmaster-7.x-3.9/

Afterwards, you can continue installation:

sudo -u aegir -s -H
drush dl --destination=/var/aegir/.drush provision-7.x-3.9
drush cache-clear drush
drush hostmaster-install
[...]
inteja’s picture

Have just updated 3.9 to 3.10 and now it looks like verify task fix permissions is changing ownership to www-data instead of aegir, so verify and backup tasks fail.

Suggestions on how to fix?

pmunch’s picture

I have a fresh Aegir 3.10 install using deb packages on Ubuntu 16.04, and I confirm that "Fix Permissions" and "Fix Ownership" make verify hosmaster task fail immediately with:

Calling hook drush_zz_fix_ownership_post_provision_verify	
sudo: no tty present and no askpass program specified	
Returned from hook drush_zz_fix_ownership_post_provision_verify	
Calling hook drush_zz_fix_permissions_post_provision_verify	
sudo: no tty present and no askpass program specified	
Returned from hook drush_zz_fix_permissions_post_provision_verify
NWOM’s picture

I can confirm #43 happening to me as well.

helmo’s picture

Please don't ask questions in a closed issue ... it doesn't show up normally, and thus doesn't get attention.

The first thing to check here is if the sudo settings have been setup correctly by the install.sh scripts. You should have files like /etc/sudoers.d/fix-drupal-platform-ownership

Please open a new issue if you have those and still see this problem.

NWOM’s picture

@helmo: Thanks for the information.

@pmunch: I created an additional issue for this here: #2961009: Sudo Settings not setup correctly in regards to Fix Drupal Platform Ownership