Problem/Motivation

At the moment when $settings['skip_permissions_hardening'] = TRUE, the system module's system_requirements unconditionally issues a warning about the site's config files' permissions without actually checking them:

      if (file_exists($full_path) && (Settings::get('skip_permissions_hardening') || !drupal_verify_install_file($full_path, FILE_EXIST | FILE_READABLE | FILE_NOT_WRITABLE))) {
        $conf_errors[] = t("The file %file is not protected from modifications and poses a security risk. You must change the file's permissions to be non-writable.", ['%file' => $full_path]);
      }

This is quite confusing and misleading (see related issues).

Proposed resolution

Drupal should either skip the checks and not issue any warnings about the state of specific conf files, or perform the checks but only issue any valid warnings (as opposed to errors).

A simple warning to remind developers not to carry this configuration over into production would seem sufficient.

Remaining tasks

* Decide whether to skip checks, or perform them and issue only valid warnings.
* Patch the existing code accordingly.
* Update tests as appropriate.

User interface changes

* Removal of invalid warnings when config file permissions are not actually incorrect.

API changes

* None.

Data model changes

* None.

Comments

mcdruid created an issue. See original summary.

mcdruid’s picture

Issue summary: View changes
mcdruid’s picture

Title: fix conf file warnings when skip_permissions_hardening is on » invalid conf file warnings when skip_permissions_hardening is on
mcdruid’s picture

Reading through the code a bit more, I can now see a reason for the existing logic:

https://api.drupal.org/api/drupal/core%21includes%21install.inc/function...

...actually tries to fix the permissions of the file according to the masks it is passed, so the existing code doesn't run the check with that function as doing so may change the existing permissions.

In which case, I'd argue we should skip the checks without issuing the warnings.

mcdruid’s picture

Status: Active » Needs review
StatusFileSize
new2.21 KB

Patch which skips the checks on config files - which is not actually a change to the behaviour, we just no longer flag up permissions warnings without actually checking those permissions.

It seems to me that some of the comments in the surrounding code are also a little bit misleading:

  // Test configuration files and directory for writability.                        
  if ($phase == 'runtime') { 

...this doesn't mention that the code is about to try and fix any incorrect permissions.

      // In normal operation, writable files or directories are an error.           
      $file_protection_severity = REQUIREMENT_ERROR;                                
      if (!drupal_verify_install_file($site_path, FILE_NOT_WRITABLE, 'dir')) {

...because drupal_verify_install_file actually tries to change the permissions if they don't initially match the mask, we only actually consider it an error if that attempt to fix the permissions fails.

I wonder if we should add a word or two of extra explanation about what the "hardening" actually is here - i.e. attempts will be made to fix incorrect permissions?

Status: Needs review » Needs work

The last submitted patch, 5: 2950851-5.patch, failed testing. View results

mcdruid’s picture

Status: Needs work » Needs review
StatusFileSize
new3.5 KB

Oops; and now with a tweak to the test because the warning produced by system_requirements is slightly different.

anavarre’s picture

Status: Needs review » Needs work

Without the patch, the default message is:

Not protected
Protection disabled
The file sites/default/settings.php is not protected from modifications and poses a security risk. You must change the file's permissions to be non-writable.
The file sites/default/settings.local.php is not protected from modifications and poses a security risk. You must change the file's permissions to be non-writable.
The file sites/default/services.yml is not protected from modifications and poses a security risk. You must change the file's permissions to be non-writable.

With the patch, the message becomes:

Not protected
Protection disabled

So, it seems to me we're removing important information as to what exactly is happening. Our issue IIUC is what we're asking the end user to do to fix the issue. As such it looks like:

  1. You must change the file's permissions to be non-writable. should be removed
  2. An indication that one of the configuration files has skip_permissions_hardening set to TRUE and it's an issue in prod, would be helpful to understand what needs to be changed.
mcdruid’s picture

Status: Needs work » Needs review
StatusFileSize
new4.17 KB

So let's make the warning that's shown when skip_permissions_hardening is enabled more explicit about the situation.

     if (Settings::get('skip_permissions_hardening')) {
-      $conf_errors[] = t('Protection disabled');
-      // If permissions hardening is disabled, then only show a warning for a
-      // writable file, as a reminder, rather than an error.
+      $conf_errors[] = t('Protection disabled: the skip_permissions_hardening setting is not recommended in production environments.');
+      // If permissions hardening is disabled, then only show a warning as a
+      // reminder, rather than an error. The config files are not actually
+      // checked as doing so may change their permissions.
anavarre’s picture

Without the patch:

Not protected
  * Protection disabled
  * The file sites/default/settings.php is not protected from modifications and poses a security risk. You must change the file's permissions to be non-writable.
  * The file sites/default/services.yml is not protected from modifications and poses a security risk. You must change the file's permissions to be non-writable.

With the patch:

Not protected
Protection disabled: the skip_permissions_hardening setting is not recommended in production environments.

I still feel we're lacking important information to understand what's going on. My sentiment is we need a) an understanding about what exactly is the consequence of enabling skip_permissions_hardening and b) how to remedy this e.g. on prod environments. What about:

Not protected
  * Protection disabled: the skip_permissions_hardening setting is not recommended in production environments.
      * The file sites/default/settings.php is not protected from modifications and poses a security risk.
      * The file sites/default/services.yml is not protected from modifications and poses a security risk.
mcdruid’s picture

The problem is that we don't know whether those config files are "protected from modifications" (i.e. are writable) or not; calling the function to verify that will change the permissions if they are writable.

I think we should avoid giving incorrect information (i.e. saying "settings.php is writable" when that may not be the case) as that just leads to confusion and frustration.

We could try to go the extra mile and actually check the permissions without trying to fix them, but that would mean using something other than drupal_verify_install_file.

I'm not sure it's worth the extra complexity of checking the permissions in a different way; the idea is simply to remind developers that they have disabled the "permissions hardening" locally, and that they'll want to ensure that setting is not carried over to production.

My vote is avoid saying anything about the actual state of specific config files because the code (as it stands) doesn't know what their permissions are.

anavarre’s picture

Status: Needs review » Reviewed & tested by the community

I guess I can live with that. Let's see what committers think.

mcdruid’s picture

Issue summary: View changes

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 9: 2950851-9.patch, failed testing. View results

anavarre’s picture

Status: Needs work » Reviewed & tested by the community

Testbot?

alexpott’s picture

Issue tags: +Needs change record
StatusFileSize
new8.02 KB
new7.59 KB

I think this issue is a bit tricky. I think @anavarre's comment in #10 is correct. What we need is a version of drupal_verify_install_file() that does not try to autofix by default. That way we could do something like

    foreach (['settings.php', 'settings.local.php', 'services.yml'] as $conf_file) {
      $full_path = $site_path . '/' . $conf_file;
      if (file_exists($full_path) && (!drupal_verify_install_file($full_path, FILE_EXIST | FILE_READABLE | FILE_NOT_WRITABLE, 'file', !Settings::get('skip_permissions_hardening')))) {
        $conf_errors[] = t("The file %file is not protected from modifications and poses a security risk. You must change the file's permissions to be non-writable.", ['%file' => $full_path]);
      }
    }

And we could change 'value' => t('Not protected'), to 'value' => t('Permissions hardening skipped'), so when it's a warning and not an error we know why.

Something like the patch attached.

alexpott’s picture

Status: Reviewed & tested by the community » Needs review

Meant to set to "needs review"

mcdruid’s picture

Assigned: Unassigned » mcdruid
Status: Needs review » Reviewed & tested by the community

I think the patch in #16 looks good; I've verified that a writable settings.php file goes from producing an error to a warning when skip_permissions_hardening is enabled.

It's an enhancement to be able to call drupal_verify_install_file() without having it actually change permissions on files when appropriate.

I'll take a look at drafting a change record for this.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 16: 2950851-16.patch, failed testing. View results

mcdruid’s picture

Status: Needs work » Reviewed & tested by the community

Hmm, testbot snafu?

mcdruid’s picture

Assigned: mcdruid » Unassigned
mcdruid’s picture

Status: Reviewed & tested by the community » Needs review

NR for the change record.

anavarre’s picture

Status: Needs review » Reviewed & tested by the community

Reviewed the CR with @mcdruid and the last iteration looks great to me.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 16: 2950851-16.patch, failed testing. View results

mcdruid’s picture

Status: Needs work » Needs review

testbot snafu?

alexpott’s picture

Status: Needs review » Reviewed & tested by the community

Yes

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 16: 2950851-16.patch, failed testing. View results

Mixologic’s picture

Status: Needs work » Reviewed & tested by the community

Testbot Snafu. Again.

  • catch committed 3663ab6 on 8.6.x
    Issue #2950851 by mcdruid, alexpott, anavarre: invalid conf file...
catch’s picture

Status: Reviewed & tested by the community » Fixed

Committed 3663ab6 and pushed to 8.6.x. Thanks!

Status: Fixed » Closed (fixed)

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