Problem/Motivation
Security issues occur. Security update will be made available at specific times. Not every Drupal user has a 24/7 SLA in place. Sometime people run sites for fun and go on holiday to remote Scottish islands and don't know if they will have internet. Drupal could provide an easy way to put a site into read only mode.
Prior art: https://www.drupal.org/project/readonlymode
Proposed resolution
There are a couple of options:
Option 1: Read only mode
Add a read only module or mode to core or just make it part of system. When enabled the module will redirect all non-safe requests to a read only page whose message can be configured by an administrator and translated via Configuration translation. The module will also strip all user content apart from the url path from the incoming request to prevent attacks where something is possible with query string parameters or cookies.
As noted by @fago this approach currently has the downside or breaking pagers and basic search. We could allow the the page or keys query parameter through after type checking them. However allowing any input is bound to make this mode less secure.
This works via a new state variable that contains a timestamp when in operation. It is a timestamp so that users can schedule a future time when the site becomes read only.
How this differs from maintenance mode
- Anonymous users can still still any content they are supposed to. This is one of the purposes of the read only mode - to still provide a working site if a user is not submitting data to it.
- No one can login until the mode has been disabled. The user that enables the mode is provided a special link with a token that can disable the mode.
Option 2: Add a site lock option to maintenance mode
Allow the user to further lock the site in maintenance mode and redirect to the maintenance page for all non-cached pages apart from a single page that unlocks the site if you have the right token. In a way this is what option 1 + maintenance mode would be like.
How this differs from maintenance mode
- No one can login until the lock has been disabled. The user that enables the lock is provided a special link with a token that can disable the lock.
Remaining tasks
User interface changes
New admin form
Maybe new module
API changes
New service to generate tokens for disabling the read only mode
Data model changes
None
| Comment | File | Size | Author |
|---|---|---|---|
| #4 | Screen Shot 2018-03-29 at 11.09.01 AM.png | 166.93 KB | webchick |
| #3 | 2957061-3.patch | 18.65 KB | alexpott |
Comments
Comment #2
vijaycs85Great idea and a missing solution in core for a long long time. +1!
Comment #3
alexpottHere's a prototype approach that adds a read only module to core.
Comment #4
webchickI really like this idea; I was in a similar boat yesterday. Obviously, we would like to ultimately do #2367319: Implement automatic background updates for highly critical security issues, but this seems like a nice interim solution.
I guess my only question would be whether or not we can hinge this off the already existing, much-better known/documented "Maintenance mode" setting vs. adding a new module. For example (just a quick mock, doesn't include scheduling options [which would also be nice for maintenance mode actually], and the help text needs work):
One other question I'd have is how does someone go about recovering from "read-only" mode, should they trigger it in the UI (regardless of where it lives)?
Comment #5
alexpottI'd be hesitant to mix the concepts since maintenance mode prevents users from seeing content too whereas the purpose of read-only mode is allow access to content but not accept any user input.
At the moment after you submit the form you have a minute after which you can switch back by submitting the form. Also on submit it provides a link that can disable the read only mode and you can just visit that link to disable the mode. The plan is also to email the user that enable the read only mode the link too.
Comment #6
alexpottI've added a section to the issue summary about how this differs from maintenance mode.
Comment #7
alexpottComment #8
naveenvalecha+1 for having this feature in core. It makes lot of sense for bloggers who don't update their sites often even on security releases.
Comment #9
David_Rothstein commentedI think this idea may have merit in its own right (as a different kind of maintenance mode that some sites might prefer) but I don't see how this is something the security team could recommend in the general case.
It isn't necessarily more secure than regular maintenance mode, just different. I can think of security issues that it would protect against that maintenance mode wouldn't, but I can also think of security issues (theoretical examples as well as real examples from the past) that it wouldn't protect against, including some that maintenance mode would protect against but that this wouldn't.
One reason for that (although not the only one) is that I don't think it really strips all user input, and probably can't if it wants to actually display the site. Consider the URL of this page:
www.drupal.org/project/ideas/issues/2957061. The "2957061" is user input. Any vulnerability that involves a dynamic menu path not being properly validated could still work with a site in read-only mode, right?In short: Keep the issue, but change the title :)
Comment #10
alexpott@David_Rothstein good point about path as user input.
I think have both maintenance mode and read only modes are possible mechanisms to mitigate and for the security team recommend is a good idea. Of course we'd prefer if sites were patched immediately but this can not always be done. This particular approach would have mitigated both SA05 and SA02. Also I'm not saying we should recommend anything in the general case but that we should disclose if maintenance mode or read only mode are mitigations in each particular case.
I've added the word "potentially" to the issue title so it's not claiming to be a panacea.
Another idea is that we could add a mode toggle that would only serve pages from page cache. In this mode you'd have to edit settings.php to get out of the read only mode. Which would add another level of security.
Comment #11
alexpottComment #12
fagoI really like the idea as well.
Initially, I was thinking this is more about pre-generating html pages, putting into some folder and redirecting requests to it. This would be perfectly fine for lots of small sites but not really feasible for larger sites with lots of content.
So just generating pages as is while stripping down things seems like the better option. However I'm not sure this is much useful when the query is stripped, as lots of stuff like paging or basic searches will be broken. Maybe they could be locked down insteads, so very basic parameters e.g. only having alphanumeric characters and values or even only whitelisted parameters are allowed?
Comment #13
chandeepkhosa commentedThis is a great idea, would be amazing to see it get implemented!
Comment #14
focus13 commentedThis is amazing idea + 1 to add the module to core.
Comment #15
alexpottI've added another option to the issue summary. All the +1 comments so far have been in favour of option 1.
Comment #16
alexpottComment #17
alexpottComment #18
alexpottComment #19
chandeepkhosa commentedWould either option 1 or 2 allow anonymous users to submit contact forms using the Contact or Webform modules?
Comment #20
alexpott@ChandeepKhosa no. That's user input.
Comment #21
mpdonadio+1 on Option 1. I can see potential uses beyond the security needs.
Some initial thoughts...
Super dumb question, but why does this need to be standalone and not part of system? And to follow policy, would this have to go in first as an experimental module?
I know you can't uninstall system.module now, but this introduces a dependency that isn't declared in the .yml
Question, why this and not the AccessInterface API?
Yeah, probably all admins to prevent someone from going rogue?
Nice comment.
Comment #22
dawehnerI certainly like this general idea! Being able to put it into read only mode would be amazing for brochure/one-off sites like events.drupal.org/paris2009.
Unlike the automated security updates idea, this module would be accepted by more conservative server admins.
In the spirit of @David_Rothstein's comment, it would be nice to cast it to an int/strip non a-z0-9 character out.
+1 for not making this a cacheable redirect :)
Nitpick: swap around the if and else in order to avoid negation
while reading this I was wondering what happens if you send a GET request with a BODY. Does PHP parse that? It seems like it totally ignores it.
Why do we not generate one hash using
\Drupal\Component\Utility\Crypt::randomBytesand store this in state tooI'm curious, why would someone swap this out?
Comment #23
iyyappan.govind+1 Great Idea!!
Comment #24
phenaproxima+1 for this. Awesome idea.
Comment #25
wim leers+1 for exploring this.
Reminds me of “Boost in core”, which is another idea issue. If the Boost technique were used, pagers would continue to work just fine. And no input would be processed at all!
Comment #26
swentel commentedI'm not running sites for fun :)
Comment #27
alexverb commentedI would suggest avoiding to put such functionality in UI if its purely considered a security or deployment measure. If the site is comprimised an active administrator could trigger hidden xss that performs counter measures.
I think the functionality has added value for some use cases, but when taking security measures the last thing you want to do is to make an admin role available to hackers by visiting the site through the browser. And readme mode or maintenance mode in UI can also be used against a live site.
If you can break a site through UI as admin it doesnt belong in UI on production.
Comment #28
aburrows commentedReally for supporting this and getting into core would be a great idea.
Comment #29
jcnventuraI like the general concept, but the details are what trouble me. Would it be possible to be pre-emptive? I.e. authorize the site to go read-only if the update module reports a pending core security release?
Comment #30
adam.weingarten commented@wim-leers,
This approach could replace traditional page-caching in Drupal.... This could have some very intriguing implications.
Comment #31
xem8vfdh commentedthis is a great idea, I'd love to see it merged when ready!
Comment #32
solideogloria commentedMaybe people would be interested in this module?
https://www.drupal.org/project/readonlymode
Or this:
https://www.drupal.org/project/config_readonly
Comment #33
borisson_I think this is a good idea but I'm not sure this should be in an initial implementation. It would make it easy to put a few sites lower on the update-list when a security release happens and not have to worry about them as much.
The implementation as-is should probably move to a real issue (in the core queue) where we can give a more in-depth review on the actual code, because that probably doesn't belong here. I just reread this issue and there hasn't really been any negative feedback on this idea, so I think that is the next step to getting this in?
Comment #34
effulgentsia commentedAs far as I know, there's no requirement for feature requests to go through the entire Ideas process: they could start as implementation issues from the beginning or move there whenever the people doing the work feel like it, and there are plenty of feature requests that have succeeded that way. However, the risk is that without the Idea being fully approved by the product management team, the implementation might go in a direction that will never get accepted into core, and that's demoralizing. https://www.drupal.org/project/ideas has more details on the process and motivation.
I agree that it looks like there is pretty good consensus here to do what's in the issue title. I was tempted to RTBC this on those grounds, so that the product management team would review it next time they meet. However, I don't think the issue summary is at a point yet to do that. For example, it mentions two options, but does not state the pros and cons of each option. Also, it says that there's prior art here in https://www.drupal.org/project/readonlymode, however neither of the two options includes some pretty key capabilities that are in that module. For example that project page says that that module includes "Easy to configure whitelist of forms that should remain available", which I'm guessing can include the login form, and that project also includes "a permission that overrides access restrictions and can be given to site administrators". I think the issue summary could more clearly spell out that this proposal intentionally doesn't include that, the security reasons for that, and what that means in terms of use-cases that this would be a good fit for vs. use-cases that would still be required to use that more feature-rich project. For example, comments like #22 and #30 seem to imply that this could be a useful setting to leave on long-term for certain kinds of sites, but I think what's being proposed in the issue summary might be too restrictive for that. Or if it's not, maybe we could add some explanation as to how (and for whom) that could work. For example: the site owner of what is essentially a static site with 0 functionality or private/member-only content could leave this setting on whenever they're not actively editing content; then when they need to edit content, they turn the setting off, make their edits, and then turn it on again? Do we have any data that supports this being an even remotely common use case? I would imagine that those are the kinds of questions that the product management team would be interested in.
Comment #35
effulgentsia commentedHere's a start at some thoughts that could maybe make their way into the issue summary...
If I'm reading the issue comments correctly, it looks to me like there are 4 scenarios that this issue could be useful for:
Does that sound about right? Are any of those scenarios incorrect and/or are there others we should add?
Comment #36
solideogloria commentedThe scenario that I was looking into it for, was that a 3rd party contractor wants to do some digging in a website to see how much work they would need to do to perform some amount of work, such as migrating from Drupal 7 to Drupal 8. It would be far more secure to let them poke around on a read-only version of the site.
Comment #37
solideogloria commentedAnother scenario: A database upgrade is required, and it requires uninstalling the old version and installing the new. During that period of time, you can switch the site to point to a backup of the database on another machine from right before the upgrade. You don't want any changes to be made, because the database/data may be changed slightly as part of the upgrade process, and the database will simply be switched over and unlocked following the upgrade. Putting the site into read-only mode allows the content to be available but unchanged, provided writing to every table is disabled. This would mean read-only access to the Drupal database.
Comment #38
quietone commentedThe Ideas project is being deprecated. This issue is moved to the Drupal project. Check that the selected component is correct. Also, add the relevant tags, especially any 'needs manager review' tags.
Comment #39
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue.
While you are making the above changes, we recommend that you convert this patch to a merge request. Merge requests are preferred over patches. Be sure to hide the old patch files as well. (Converting an issue to a merge request without other contributions to the issue will not receive credit.)