mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merge branch '4.5' into 4
This commit is contained in:
commit
7da77be5ce
@ -271,19 +271,16 @@ the shortcode references the database identifier of the `Image` object.
|
||||
|
||||
### Controlling how CMS users interact with versioned DataObjects
|
||||
|
||||
By default the versioned module includes a `VersionedGridfieldDetailForm` that can extend gridfield with versioning support for models.
|
||||
By default the versioned module includes a `VersionedGridfieldDetailForm` that extends gridfield with versioning support for DataObjects.
|
||||
|
||||
You can enable this on a per-model basis using the following code:
|
||||
You can disable this on a per-model basis using the following code:
|
||||
|
||||
```php
|
||||
<?php
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\Versioned\Versioned;
|
||||
class MyBanner extends DataObject {
|
||||
private static $extensions = [
|
||||
Versioned::class,
|
||||
];
|
||||
private static $versioned_gridfield_extensions = true;
|
||||
private static $versioned_gridfield_extensions = false;
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -21,28 +21,59 @@ $ ./vendor/bin/sake dev/tasks/MigrateFileTask
|
||||
|
||||
This task will perform a number of subtasks:
|
||||
|
||||
- `move-files`: Migrates existing `File` objects by adding required metadata to the database (incl. versioning).
|
||||
By default, it will not move files on the filesystem (starting with [4.4.0](/changelogs/4.4.0)).
|
||||
Publishes to the live stage to ensure
|
||||
that previously visible assets remain visible to the public site.
|
||||
If additional security or visibility rules should be applied to `File`, then
|
||||
make sure to correctly extend `canView` via extensions.
|
||||
- `move-thumbnails`: Move existing thumbnails, rather than have them generated on the fly.
|
||||
This task is optional, but helps to avoid growing your asset folder (no duplicate thumbnails)
|
||||
- `generate-cms-thumbnails`: The new CMS UI needs different thumbnail sizes, which can be pregenerated.
|
||||
This can be a CPU and memory intensive task for large asset stores.
|
||||
See [Migrating substantial number of files](#performance)
|
||||
- `fix-secureassets`: Migrates files secured through the [silverstripe/secureassets](https://github.com/silverstripe/silverstripe-secureassets) module.
|
||||
Ensures that previous `.htaccess` folder protections don't interfere with 4.x-style asset protections.
|
||||
- `fix-folder-permissions`: Fixes folder permissions which might have been broken by
|
||||
previously using the [silverstripe/secureassets](https://github.com/silverstripe/silverstripe-secureassets)
|
||||
- `move-files`: Migrates existing `File` objects by adding required metadata to the database (incl. versioning).
|
||||
By default, it will not move files on the filesystem (starting with [4.4.0](/changelogs/4.4.0)).
|
||||
Publishes to the live stage to ensure
|
||||
that previously visible assets remain visible to the public site.
|
||||
If additional security or visibility rules should be applied to `File`, then
|
||||
make sure to correctly extend `canView` via extensions.
|
||||
- `migrate-folders`: Migrates existing `Folder` objects by adding metadata to the
|
||||
database (incl. versioning). This subtask does not perform any operations with the actual
|
||||
file system. It merely updates the database records.
|
||||
- `move-thumbnails`: Move existing thumbnails, rather than have them generated on the fly.
|
||||
This task is optional, but helps to avoid growing your asset folder (no duplicate thumbnails)
|
||||
- `generate-cms-thumbnails`: The new CMS UI needs different thumbnail sizes, which can be pregenerated.
|
||||
This can be a CPU and memory intensive task for large asset stores.
|
||||
See [Migrating substantial number of files](#performance)
|
||||
- `fix-secureassets`: Migrates files secured through the [silverstripe/secureassets](https://github.com/silverstripe/silverstripe-secureassets) module.
|
||||
Ensures that previous `.htaccess` folder protections don't interfere with 4.x-style asset protections.
|
||||
- `fix-folder-permissions`: Fixes folder permissions which might have been broken by
|
||||
previously using the [silverstripe/secureassets](https://github.com/silverstripe/silverstripe-secureassets)
|
||||
|
||||
One or more subtasks can be run individually through the `only` argument.
|
||||
Example: `only=move-files,move-thumbnails`
|
||||
|
||||
The `move-files` and `migrate-folders` subtasks are mandatory. Without running them,
|
||||
your database will be left in an inconsistent state.
|
||||
|
||||
The output is quite verbose by default. Look for `WARNING` and `ERROR` in the log files.
|
||||
When executing the task on CLI, you'll get colour coded error messages.
|
||||
|
||||
### Specialised opt-in file migration subtasks
|
||||
Some subtasks are only necessary in specific situations. Those subtasks will not be run by default and must be explicitly referenced via the `only` parameter.
|
||||
|
||||
- `normalise-access`: This subtask identifies physical files that are
|
||||
inadvertently exposed to the public and moves them to a protected location.
|
||||
Until the release of Silverstripe CMS 4.3.5/4.4.4 in September 2019,
|
||||
Silverstripe CMS stored protected files in publicly accessible locations
|
||||
when the files were created from a "LIVE" versioned context. This commonly
|
||||
occur when a user uploaded a file in a user form.
|
||||
[CVE-2019-12245 patch](https://www.silverstripe.org/download/security-releases/CVE-2019-12245)
|
||||
addressed this issue preventing the exposure of new files. However, this patch
|
||||
did not retroactively protect files that had been exposed. You should run this
|
||||
task at least once if your Silverstripe CMS project was created prior to
|
||||
September 2019.
|
||||
- `relocate-userform-uploads-2020-9280`: This subtask is specific to the
|
||||
`silverstripe/userforms` module. Because of the
|
||||
[CVE-2020-9280](https://www.silverstripe.org/download/security-releases/CVE-2020-9280)
|
||||
vulnerability, if your project was migrated from Silverstripe CMS 3, the
|
||||
migrated user forms might upload files in wrong folders. This subtask goes
|
||||
through all files uploaded via user forms and moves them to their intended
|
||||
locations.
|
||||
|
||||
Read the [Silverstripe CMS 4.4.6 change logs](/changelogs/4.4.6) to learn more
|
||||
about the `normalise-access` and `relocate-userform-uploads-2020-9280` subtasks.
|
||||
|
||||
## Background migration through the Queuedjobs module
|
||||
|
||||
In general, it's safest to run the file migration on a non-production environment,
|
||||
@ -65,7 +96,7 @@ are configured to run jobs automatically without time limits
|
||||
[2](https://www.cwp.govt.nz/developer-docs/en/2/working_with_projects/infrastructural_considerations/)).
|
||||
It is not recommended to run
|
||||
[multiple processes](https://github.com/symbiote/silverstripe-queuedjobs/blob/master/docs/en/configuring-multi-process-execution.md)
|
||||
when executing the file migration job.
|
||||
when executing the file migration job.
|
||||
|
||||
## Migration of existing thumbnails
|
||||
|
||||
@ -123,7 +154,7 @@ and [File Security: Protected file headers](file_security#protected_file_headers
|
||||
## Migrating substantial numbers of files {#performance}
|
||||
|
||||
The time it takes to run the file migration will depend on the number of files and their size. The generation of thumbnails will depend on the number and dimension of your images.
|
||||
In general, the migration task can be restarted if it times out, and will continue where it left off.
|
||||
In general, the migration task can be restarted if it times out, and will continue where it left off.
|
||||
|
||||
If you are migrating a substantial number of files, you should run the file migration task either as a queued job or on the command line. If the migration task fails or times out, you can start it again and it will pick up where it left off.
|
||||
|
||||
@ -131,7 +162,7 @@ If your environment supports the _Imagick_ PHP library, you may want to use that
|
||||
|
||||
[Changing the image manipulation driver to Imagick](images#changing-the-manipulation-driver-to-imagick)
|
||||
|
||||
If your project hosts big images (e.g. 4K images), this can also affect the amount of memory used to generate the thumbnails. The file migration task assumes that it will have at least 512MB of memory available.
|
||||
If your project hosts big images (e.g. 4K images), this can also affect the amount of memory used to generate the thumbnails. The file migration task assumes that it will have at least 512MB of memory available.
|
||||
|
||||
By default the file migration task will not generate thumbnails for files greater than 9MB to avoid exhausting the available memory. To increase this limit, add the following code to your YML configuration:
|
||||
|
||||
|
458
docs/en/04_Changelogs/4.4.6.md
Normal file
458
docs/en/04_Changelogs/4.4.6.md
Normal file
@ -0,0 +1,458 @@
|
||||
# 4.4.6
|
||||
|
||||
## Security patches
|
||||
|
||||
This release is a security hotfix. It only contains security fixes essential to
|
||||
addressing the CVE-2020-9280 security issue and follow up work from the
|
||||
CVE-2019-12245 patch which was released in September 2019.
|
||||
|
||||
* [Read the CVE-2020-9280 security disclosure](https://www.silverstripe.org/download/security-releases/CVE-2020-9280)
|
||||
from April 2020
|
||||
* [Read the CVE-2019-12245 security disclosure](https://www.silverstripe.org/download/security-releases/CVE-2019-12245)
|
||||
from September 2019
|
||||
|
||||
|
||||
**Simply applying the patch might NOT be enough.** Some files that were uploaded
|
||||
or created prior to the application of the CVE-2020-9280/CVE-2019-12245 patches
|
||||
may be left exposed to the public. You may need to run some additional file
|
||||
migration tasks to protect those files.
|
||||
|
||||
This release is especially important for Silverstripe CMS projects using the
|
||||
`silverstripe/userforms` module, but all project owners should consider
|
||||
upgrading as soon as convenient.
|
||||
|
||||
If your project was migrated from Silverstripe CMS 3, you need to run the new
|
||||
`migrate-folders` task.
|
||||
|
||||
## What does this release fix?
|
||||
|
||||
### CVE-2020-9280: Folders migrated from Silverstripe CMS 3 may be unsafe to upload to (CVSS 5.9)
|
||||
|
||||
Files uploaded via Forms to folders migrated from Silverstripe CMS 3.x may be
|
||||
put to the default `/Uploads` folder instead. Uploads performed via the CMS UI
|
||||
are not affected. This is a security issue because the default `/Uploads` folder
|
||||
is publicly accessible by default, which means the uploaded files may be
|
||||
accessed by unauthorised parties via HTTP by guessing the file name. This
|
||||
affects installations which allowed upload folder protection via the optional
|
||||
`silverstripe/secureassets` module under 3.x. This module is installed and
|
||||
enabled by default on the Common Web Platform (CWP). The vulnerability only
|
||||
affects files uploaded after an upgrade to 4.x.
|
||||
|
||||
[Read the CVE-2020-9280 security disclosure](https://www.silverstripe.org/download/security-releases/CVE-2020-9280)
|
||||
|
||||
### CVE-2019-12245 follow up work
|
||||
|
||||
In September 2019, Silverstripe CMS 4.3.6 and 4.4.4 were released to address an
|
||||
issue that caused files to be stored in a publicly accessible location. Files
|
||||
that were uploaded via the userforms module could have been affected. Files
|
||||
uploaded via a custom form or programmatically created could also have been
|
||||
affected.
|
||||
|
||||
While those older releases prevented the exposure of new files, they did not
|
||||
retroactively protect files that had already been exposed prior to the patch.
|
||||
These new releases provide a mechanism to protect files wrongly exposed to the
|
||||
public.
|
||||
|
||||
* [Read the CVE-2019-12245 security disclosure](https://www.silverstripe.org/download/security-releases/CVE-2019-12245)
|
||||
* [Read the Silverstripe CMS 4.3.6 change logs](4.3.6)
|
||||
* [Read the Silverstripe CMS 4.4.4 change logs](4.4.4)
|
||||
|
||||
## What are the technical details of the vulnerabilities?
|
||||
|
||||
### CVE-2020-9280
|
||||
|
||||
The root cause of the problem is that the file migration task would not create
|
||||
"Live" records for Folders migrated from Silverstripe CMS 3 prior to this patch.
|
||||
This may lead to inconsistencies between the database state and what the actual
|
||||
application gets from the ORM when performing its business logic.
|
||||
|
||||
This affects the `silverstripe/userforms` module and can cause user forms to
|
||||
save uploaded files in the default "Uploads" folder. Custom forms built with
|
||||
`Silverstripe\Forms` or `Silverstripe\Assets` components can also be
|
||||
susceptible to this behaviour.
|
||||
|
||||
Considering user forms as an example. Let's say you have an EditableFileField,
|
||||
that keeps an ID of a folder to upload to as an `has_one` relationship. When the
|
||||
submission happens with a `Stage=Live` context, the ORM cannot fetch the
|
||||
`Folder` instance, since it doesn't exist in the `Live` stage. When the upload
|
||||
Folder is undefined, the default `Silverstripe\FileField` implementation falls
|
||||
back to the default "Uploads" Folder, which is public by default.
|
||||
|
||||
### CVE-2019-12245
|
||||
|
||||
Prior the 4.3.6/4.4.4 release, the `File::canView()` method could
|
||||
return an erroneous value for anonymous users when the file was being created or
|
||||
uploaded from a "Live" stage. When creating a new File in a Live stage, this
|
||||
could cause the file to be stored in a publicly accessible location when it was
|
||||
meant to be protected.
|
||||
|
||||
This could occur when:
|
||||
* a file was submitted in a user form upload field
|
||||
* a file was submitted in a custom form
|
||||
* a file was programmatically created by custom logic.
|
||||
|
||||
It would not occur when uploading a file via the asset administration area in
|
||||
the CMS.
|
||||
|
||||
### How do I know if the files are actually exposed?
|
||||
|
||||
Even if your project creates files programmatically or receives them via a
|
||||
custom form, your files might not have been exposed. Whether your files have
|
||||
been exposed depends on your exact implementation.
|
||||
|
||||
There's two ways to verify if files are exposed:
|
||||
* look directly at the file system
|
||||
* try to access files in an incognito/private browser session.
|
||||
|
||||
If you have direct access to the file system or to a snapshot of your live data,
|
||||
you can look directly at the files. To do that, access your `assets` directory
|
||||
which will either be located in your project root or under the `public`
|
||||
directory. The assets directory will contain an hidden `.protected` directory
|
||||
which contains restricted and draft files. Other files which are not stored
|
||||
under the `.protected` directory will be visible to anonymous users. If you can
|
||||
see files that are meant to be confidential outside of the `.protected` folder,
|
||||
then they are accessible by the general public.
|
||||
|
||||
Some files may be stored under a _hash path_. This means that the physical files
|
||||
will be stored in a folder with a 10 character hexadecimal name. e.g.: If your
|
||||
File is stored under `secret/folder/condfidential.pdf` in the CMS, the physical
|
||||
file might be stored under a path similar to
|
||||
`public/assets/secret/folder/c0f7cbd745/condfidential.pdf`.
|
||||
|
||||
[Learn what's the difference between _natural paths_ and _hash paths_](https://docs.silverstripe.org/en/4/developer_guides/files/file_migration/#natural-path-vs-hash-path)
|
||||
on the Silverstripe CMS documentation.
|
||||
|
||||
Alternatively, you can try accessing the file directly in a incognito/private
|
||||
browser session. To do so, navigate to a restricted file in the asset
|
||||
administration interface inside the CMS. On the right-hand panel,
|
||||
right-click on the file preview and copy the link to the file. If you paste the
|
||||
link into a private/incognito browser session and can access the file, then your
|
||||
file can be viewed by the general public.
|
||||
|
||||
## Running the migration tasks
|
||||
|
||||
The 4.4.6/4.5.2 Silverstripe CMS releases add new file migration subtasks to
|
||||
retroactively protect files that have been wrongly exposed. They are 3 new
|
||||
subtasks.
|
||||
|
||||
* `migrate-folders` creates versioning metadata for Silverstripe CMS 3 Folder
|
||||
records.
|
||||
* `normalise-access` protect files that have been wrongly exposed.
|
||||
* `relocate-userform-uploads-2020-9280` move files uploaded through the
|
||||
userforms module to their intended folder.
|
||||
|
||||
### Do I need to run the migration tasks?
|
||||
|
||||
Based on the nature of your Silverstripe CMS project, you may need to run all of
|
||||
the tasks, some of the them, or none of them.
|
||||
|
||||
You do not need to run any of the subtasks if the following three conditions are
|
||||
all true:
|
||||
* your project was not migrated from Silverstripe CMS 3
|
||||
* your project does not include the userforms module, or if it does, no userform
|
||||
has been configured to allow file uploads
|
||||
* your project does not programmatically create files or allow users to upload
|
||||
files via a custom form(s).
|
||||
|
||||
If your project was upgraded from a Silverstripe CMS 3 project, you should
|
||||
minimally run the `migrate-folders` subtask.
|
||||
|
||||
If your project programmatically creates files or allows users to upload files
|
||||
via a user form or a custom form, you should run the `normalise-access` task.
|
||||
|
||||
If your project allows users to upload files via a user form and was upgraded from
|
||||
a Silverstripe CMS 3 project, you may need to run all 3 tasks.
|
||||
|
||||
If your project was migrated from Silverstripe CMS 3 and allows users to upload
|
||||
files via custom forms, you should run the `migrate-folders` subtask. However,
|
||||
you also will need to manually protect the affected files. The easiest way
|
||||
could be to find all the folders affected through a SQL query before you run the
|
||||
task. Then you may be able to find all the custom forms using those folder IDs
|
||||
accordingly. Unfortunately, we cannot provide any automation for this scenario.
|
||||
|
||||
You should also consider making your `/Uploads` folder protected manually
|
||||
(via CMS) as a best practice, since it is publicly accessible by default.
|
||||
|
||||
### What do the migration tasks do?
|
||||
|
||||
Take some time to read the following descriptions and understand how running
|
||||
each subtask will affect your Silverstripe CMS project. `migrate-folders` and
|
||||
`normalise-access` are relatively quick and have no side affects.
|
||||
|
||||
`relocate-userform-uploads-2020-9280` is the most complex of the three subtasks
|
||||
and has the most potential side effects. You should take special care to
|
||||
understand what it does before running it.
|
||||
|
||||
#### migrate-folders subtask
|
||||
|
||||
The `migrate-folders` subtask validates that every "Folder" record in the
|
||||
`File` table has a matching entry in the `File_Live` table. This will prevent
|
||||
future file uploads from being accidentally stored in the publicly accessible
|
||||
"Uploads" folder.
|
||||
|
||||
It does not retroactively move files that have been stored in the wrong Folder
|
||||
to their intended destination.
|
||||
|
||||
To find out what Folders on your Silverstripe CMS project will be affected by
|
||||
running the `migrate-folders` subtask, you can run the following SQL query:
|
||||
|
||||
```sql
|
||||
-- This query is targeted to MySQL. You may need to adapt it for other SQL databases.
|
||||
SELECT
|
||||
File.ID,
|
||||
File.Name
|
||||
FROM
|
||||
File
|
||||
LEFT JOIN
|
||||
File_Live
|
||||
ON File_Live.ID = File.ID
|
||||
WHERE
|
||||
File_Live.ID IS NULL
|
||||
AND File.ClassName = 'SilverStripe\\Assets\\Folder'
|
||||
```
|
||||
|
||||
Note that the file migration task will now run this step by default, so you
|
||||
won't need to explicitly run the `migrate-folders` task for future
|
||||
Silverstripe CMS 3 upgrades.
|
||||
|
||||
[Learn how to migrate files from Silverstripe CMS 3 to Silverstripe CMS 4](https://docs.silverstripe.org/en/4/developer_guides/files/file_migration/#migration-from-silverstripe-3-to-silverstripe-4-4-or-later)
|
||||
on the Silverstripe CMS documentation.
|
||||
|
||||
#### normalise-access subtask
|
||||
|
||||
The `normalise-access` subtask goes through each individual File record in a
|
||||
Silverstripe CMS project and confirms that the `canView` result for anonymous
|
||||
users matches the physical location of the file. If the physical file is
|
||||
publicly visible while it's `canView` method returns `false` for anonymous
|
||||
users, it will be moved to the protected location.
|
||||
|
||||
#### relocate-userform-uploads-2020-9280 task
|
||||
|
||||
Because of the `CVE-2020-9280` vulnerability, you may have Folders without a
|
||||
matching entries in their "Live" table. User form file upload submissions
|
||||
may end up being stored in an incorrect publicly-accessible location under the
|
||||
following conditions:
|
||||
* you have user forms that accept file uploads
|
||||
* the file upload field is configured to save the file in a folder that was
|
||||
created in Silverstripe CMS 3
|
||||
* the targeted folder has not been manually saved since your Silverstripe CMS 4
|
||||
upgrade.
|
||||
|
||||
If those 3 conditions are met, you should consider running the
|
||||
`relocate-userform-uploads-2020-9280` subtask.
|
||||
|
||||
`relocate-userform-uploads-2020-9280` will go through each user form file upload
|
||||
submission and verify that the uploaded file is stored in the folder specified
|
||||
in the matching file upload user form field. If the file is stored in the wrong
|
||||
folder, the task will move the file to the Folder specified in the user form
|
||||
upload field configuration at the time the file was uploaded.
|
||||
|
||||
##### What if I have a custom upload form?
|
||||
|
||||
If you have a written a controller operating in the "Live" stage that creates
|
||||
files or receives uploaded files, and that controller is configured to save
|
||||
files in a folder created in Siverstripe CMS 3, your files may have been stored
|
||||
in the wrong location. Unfortunately, we can not provide a migration task for
|
||||
each custom scenario.
|
||||
|
||||
The `relocate-userform-uploads-2020-9280` only works because there's a record of
|
||||
where the file was meant to be uploaded on the user form page.
|
||||
|
||||
If you have a small number of files, it might be practical to manually update
|
||||
their location via the asset administration interface in the CMS. Otherwise, you
|
||||
may have to write your own migration task to achieve the same purpose.
|
||||
|
||||
### How do I run the migration tasks?
|
||||
|
||||
`migrate-folders`, `normalise-access` and `relocate-userform-uploads-2020-9280`
|
||||
have been written as subtasks of the regular file migration task. The file
|
||||
migration task can be run in 3 different ways:
|
||||
* in the browser under `dev/tasks`
|
||||
* on the command line
|
||||
* as a queued job.
|
||||
|
||||
You can run each subtask individually or you can run all three subtasks in one
|
||||
go. The `only` parameter controls which subtasks will be run. You can get
|
||||
multiple subtask to run by specifying them as a comma-separated list:
|
||||
`only=migrate-folders,normalise-access,relocate-userform-uploads-2020-9280`. The subtasks
|
||||
are executed in a pre-defined sequence, so the order they appeared in the
|
||||
comma-separated list is irrelevant.
|
||||
|
||||
Which ever way you choose to run the sub tasks, you **MUST run `migrate-folders`
|
||||
before `relocate-userform-uploads-2020-9280`**. The recommended order to run the subtasks
|
||||
is:
|
||||
1. `migrate-folders`
|
||||
2. `normalise-access`
|
||||
3. `relocate-userform-uploads-2020-9280`.
|
||||
|
||||
[Learn more about the File Migration Task on the Silverstripe CMS documentation](https://docs.silverstripe.org/en/4/developer_guides/files/file_migration/)
|
||||
|
||||
#### Testing the file migration task first
|
||||
|
||||
If possible, you should consider running the task in a development or testing
|
||||
environment first, either on a snapshot of your production environment or on a
|
||||
subset of your live data. Make sure you have back ups configured on your
|
||||
production environment and a recovery strategy in place in case things go badly.
|
||||
|
||||
#### Running the task in the browser
|
||||
|
||||
Running the file migration task in the browser should only be considered if you
|
||||
have a small number of files. It is susceptible to timeout if the task runs for
|
||||
too long. Depending on your application settings, you may not have the output
|
||||
logs of the tasks run. Please consider the other options first.
|
||||
|
||||
To run the task in the browser, navigate to `/dev/tasks/MigrateFileTask` and
|
||||
provide the `only` parameter as a GET parameter on your request. e.g.:
|
||||
`https://example.com/dev/tasks/MigrateFileTask?only=migrate-folders`
|
||||
|
||||
If you're running this task on a production environment, you will be asked to
|
||||
login using administrator credentials and you will be prompted to confirm you
|
||||
want to execute the task.
|
||||
|
||||
#### Running the task on the command line
|
||||
|
||||
Navigate to your project root on the command line and use the sake utility to
|
||||
execute the `MigrateFileTask` command.
|
||||
|
||||
```bash
|
||||
./vendor/bin/sake dev/tasks/MigrateFileTask only=migrate-folders
|
||||
```
|
||||
|
||||
[Learn how to execute Silverstripe CMS tasks on the command line](https://docs.silverstripe.org/en/4/developer_guides/cli/)
|
||||
|
||||
#### Running the task as a queued job
|
||||
|
||||
If you've installed the
|
||||
[queued-jobs module](https://github.com/symbiote/silverstripe-queuedjobs) on
|
||||
your Silverstripe CMS project, you can run the file migration task as a queued
|
||||
job. There are two alternative ways to schedule a task to run as a queued job:
|
||||
* by navigating to the task URL in your browser (e.g.:
|
||||
`https://example.com/dev/tasks/queue/MigrateFileTask?only=migrate-folders`)
|
||||
* via the command line (e.g.
|
||||
`vendor/bin/sake dev/tasks/queue/MigrateFileTask only=migrate-folders`).
|
||||
|
||||
Once the task has been scheduled, you can monitor its progress in the queued job
|
||||
administration area inside the CMS.
|
||||
|
||||
### How long should I expect the migration tasks to run for?
|
||||
|
||||
#### migrate-folders
|
||||
|
||||
The main factor in the execution time of the `migrate-folders` subtask is the
|
||||
number of Folders to migrate.
|
||||
|
||||
This subtask does not perform any filesystem operations. It mostly performs read
|
||||
and write SQL queries.
|
||||
|
||||
You can expect 20 to 30 Folders to be migrated per second. A project with
|
||||
10,000 Folders to migrate should take less than 10 minutes.
|
||||
|
||||
#### normalise-access
|
||||
|
||||
The main factor in the execution time of the `normalise-access` subtask are:
|
||||
* the number of files to protect
|
||||
* the number of files in the same folder.
|
||||
|
||||
Protecting 1000 folders with 1 file each will be considerably faster than 1
|
||||
folder with 1000 files. The total number of files in your project will also
|
||||
impact the subtask runtime, but to a lesser extent.
|
||||
|
||||
This substask performs a lot of file system operations with some read SQL
|
||||
queries. It does not write data to the database.
|
||||
|
||||
You can expect 10 to 20 files to be protected per seconds. Performance is
|
||||
degraded if all those files are in a small number of folders.
|
||||
|
||||
* A project with 10,000 files to protected spread through a lot of folders
|
||||
should take less than an hour.
|
||||
* A project with 10,000 files to protected all in one folder can take several
|
||||
hours.
|
||||
|
||||
#### relocate-userform-uploads-2020-9280
|
||||
|
||||
The main factor in the execution time of the `normalise-access` subtask are:
|
||||
* the number of files to protect
|
||||
* the number of files in the same folder.
|
||||
|
||||
Moving 1000 folders with 1 file each will be considerably faster than 1 folder
|
||||
with 1000 files.
|
||||
|
||||
This substask performs a mix of file system operations and read/write SQL
|
||||
queries.
|
||||
|
||||
The approximate speed of the task is:
|
||||
- 500 files per minute with 1k files in the same folder (9 files per second)
|
||||
- 60 files per minute with 10k files in the same folder (1 file per second).
|
||||
|
||||
## Edges cases and potential "gotchas"
|
||||
|
||||
### I don't have "/Uploads" folder in CMS
|
||||
|
||||
Either the default "Uploads" folder was changed via
|
||||
[Silverstripe\Assets\Upload::uploads_folder](https://api.silverstripe.org/4/SilverStripe/Assets/Upload.html)
|
||||
configuration parameter, or you don't have any files uploaded to it.
|
||||
|
||||
The issues covered by this patch may still affect your application.
|
||||
|
||||
### I have two "/Uploads" folders in CMS
|
||||
If you see two /Uploads folders in CMS, most likely that means one of them was
|
||||
migrated from Silverstripe CMS 3, whereas some application logic created the
|
||||
second copy after the migration.
|
||||
|
||||
In that case your database would contain a record in the `File` table for each
|
||||
of them, while `File_Live` table would only have a record about the other one.
|
||||
|
||||
After running the tasks provided in this patch, we suggest you manually move all
|
||||
content from one Folder to the other via the CMS. Then remove the empty folder.
|
||||
|
||||
### What if I updated my files after upload?
|
||||
|
||||
Beware that draft files are present in 2 locations on the filesystem.
|
||||
|
||||
* The original live version of the file is still available.
|
||||
* The draft version of the file should be present in a `.protected` folder that
|
||||
is inaccessible for unauthenticated users.
|
||||
|
||||
This means that even if you moved a file but don't publish it, the live version
|
||||
of the file will still be available.
|
||||
|
||||
To address this, "relocate-userform-uploads-2020-9280" task only works on the
|
||||
very first version of a file if it's published. Subsequent versions of the file
|
||||
are ignored by the task. For example, even if you didn't change the location of
|
||||
a file, but updated the filename or its permissions, the script will ignore that
|
||||
file.
|
||||
|
||||
If you have an unpublished draft, but the live version of the file is 1 (no
|
||||
published changes after upload), the script will try to move the live version of
|
||||
the file into its originally intended location, while preserving the current
|
||||
draft version of the file as-is. This would increment numbers for both Live and
|
||||
Draft versions of the file, while moving the live version to another location
|
||||
(both on the file system and in the CMS).
|
||||
|
||||
### Files with draft access restriction
|
||||
|
||||
If you have a published file that is publicly available and you update the draft
|
||||
version to restrict read access, the live file currently remains accessible
|
||||
until you publish the draft version. However, the `canView` method on the live
|
||||
file will immediately start returning `false` for anonymous users.
|
||||
|
||||
This will cause `normalise-access` to protect the live file. Beware that if
|
||||
you have unpublished access restrictions on draft files, those will take effect
|
||||
on the live file after running `normalise-access`.
|
||||
|
||||
Read the ["Files with access restriction in Draft" GitHub issue](https://github.com/silverstripe/silverstripe-assets/issues/385)
|
||||
for more details.
|
||||
|
||||
<!--- Changes below this line will be automatically regenerated -->
|
||||
|
||||
<<<<<<< HEAD
|
||||
## Change Log
|
||||
|
||||
### Bugfixes
|
||||
|
||||
* 2020-03-09 [6779fd3](https://github.com/silverstripe/silverstripe-assets/commit/6779fd3c8c1c05a3db5035bf6e541c9483d161fc) Add FolderMigrationHelper
|
||||
* 2020-03-08 [b269d8749](https://github.com/silverstripe/silverstripe-framework/commit/b269d874909cd70bb60c1a2974ea5446b43b0436) Register new sub tasks to fix files affected by CVE-2020-9280 and CVE-2019-12245 (Serge Latyntcev)
|
||||
* 2020-03-04 [12ea7cd](https://github.com/silverstripe/silverstripe-assets/commit/12ea7cd2037bebcb3196dd5e3aaa72e6dbc7c7b2) Create NormaliseAccessMigrationHelper to fix files affected by CVE-2019-12245 (Maxime Rainville)
|
||||
=======
|
||||
>>>>>>> 4.5.3
|
||||
<!--- Changes above this line will be automatically regenerated -->
|
455
docs/en/04_Changelogs/4.5.2.md
Normal file
455
docs/en/04_Changelogs/4.5.2.md
Normal file
@ -0,0 +1,455 @@
|
||||
# 4.5.2
|
||||
|
||||
## Security patches
|
||||
|
||||
This release is a security hotfix. It only contains security fixes essential to
|
||||
addressing the CVE-2020-9280 security issue and follow up work from the
|
||||
CVE-2019-12245 patch which was released in September 2019.
|
||||
|
||||
* [Read the CVE-2020-9280 security disclosure](https://www.silverstripe.org/download/security-releases/CVE-2020-9280)
|
||||
from April 2020
|
||||
* [Read the CVE-2019-12245 security disclosure](https://www.silverstripe.org/download/security-releases/CVE-2019-12245)
|
||||
from September 2019
|
||||
|
||||
|
||||
**Simply applying the patch might NOT be enough.** Some files that were uploaded
|
||||
or created prior to the application of the CVE-2020-9280/CVE-2019-12245 patches
|
||||
may be left exposed to the public. You may need to run some additional file
|
||||
migration tasks to protect those files.
|
||||
|
||||
This release is especially important for Silverstripe CMS projects using the
|
||||
`silverstripe/userforms` module, but all project owners should consider
|
||||
upgrading as soon as convenient.
|
||||
|
||||
If your project was migrated from Silverstripe CMS 3, you need to run the new
|
||||
`migrate-folders` task.
|
||||
|
||||
## What does this release fix?
|
||||
|
||||
### CVE-2020-9280: Folders migrated from Silverstripe CMS 3 may be unsafe to upload to (CVSS 5.9)
|
||||
|
||||
Files uploaded via Forms to folders migrated from Silverstripe CMS 3.x may be
|
||||
put to the default `/Uploads` folder instead. Uploads performed via the CMS UI
|
||||
are not affected. This is a security issue because the default `/Uploads` folder
|
||||
is publicly accessible by default, which means the uploaded files may be
|
||||
accessed by unauthorised parties via HTTP by guessing the file name. This
|
||||
affects installations which allowed upload folder protection via the optional
|
||||
`silverstripe/secureassets` module under 3.x. This module is installed and
|
||||
enabled by default on the Common Web Platform (CWP). The vulnerability only
|
||||
affects files uploaded after an upgrade to 4.x.
|
||||
|
||||
[Read the CVE-2020-9280 security disclosure](https://www.silverstripe.org/download/security-releases/CVE-2020-9280)
|
||||
|
||||
### CVE-2019-12245 follow up work
|
||||
|
||||
In September 2019, Silverstripe CMS 4.3.6 and 4.4.4 were released to address an
|
||||
issue that caused files to be stored in a publicly accessible location. Files
|
||||
that were uploaded via the userforms module could have been affected. Files
|
||||
uploaded via a custom form or programmatically created could also have been
|
||||
affected.
|
||||
|
||||
While those older releases prevented the exposure of new files, they did not
|
||||
retroactively protect files that had already been exposed prior to the patch.
|
||||
These new releases provide a mechanism to protect files wrongly exposed to the
|
||||
public.
|
||||
|
||||
* [Read the CVE-2019-12245 security disclosure](https://www.silverstripe.org/download/security-releases/CVE-2019-12245)
|
||||
* [Read the Silverstripe CMS 4.3.6 change logs](4.3.6)
|
||||
* [Read the Silverstripe CMS 4.4.4 change logs](4.4.4)
|
||||
|
||||
## What are the technical details of the vulnerabilities?
|
||||
|
||||
### CVE-2020-9280
|
||||
|
||||
The root cause of the problem is that the file migration task would not create
|
||||
"Live" records for Folders migrated from Silverstripe CMS 3 prior to this patch.
|
||||
This may lead to inconsistencies between the database state and what the actual
|
||||
application gets from the ORM when performing its business logic.
|
||||
|
||||
This affects the `silverstripe/userforms` module and can cause user forms to
|
||||
save uploaded files in the default "Uploads" folder. Custom forms built with
|
||||
`Silverstripe\Forms` or `Silverstripe\Assets` components can also be
|
||||
susceptible to this behaviour.
|
||||
|
||||
Considering user forms as an example. Let's say you have an EditableFileField,
|
||||
that keeps an ID of a folder to upload to as an `has_one` relationship. When the
|
||||
submission happens with a `Stage=Live` context, the ORM cannot fetch the
|
||||
`Folder` instance, since it doesn't exist in the `Live` stage. When the upload
|
||||
Folder is undefined, the default `Silverstripe\FileField` implementation falls
|
||||
back to the default "Uploads" Folder, which is public by default.
|
||||
|
||||
### CVE-2019-12245
|
||||
|
||||
Prior the 4.3.6/4.4.4 release, the `File::canView()` method could
|
||||
return an erroneous value for anonymous users when the file was being created or
|
||||
uploaded from a "Live" stage. When creating a new File in a Live stage, this
|
||||
could cause the file to be stored in a publicly accessible location when it was
|
||||
meant to be protected.
|
||||
|
||||
This could occur when:
|
||||
* a file was submitted in a user form upload field
|
||||
* a file was submitted in a custom form
|
||||
* a file was programmatically created by custom logic.
|
||||
|
||||
It would not occur when uploading a file via the asset administration area in
|
||||
the CMS.
|
||||
|
||||
### How do I know if the files are actually exposed?
|
||||
|
||||
Even if your project creates files programmatically or receives them via a
|
||||
custom form, your files might not have been exposed. Whether your files have
|
||||
been exposed depends on your exact implementation.
|
||||
|
||||
There's two ways to verify if files are exposed:
|
||||
* look directly at the file system
|
||||
* try to access files in an incognito/private browser session.
|
||||
|
||||
If you have direct access to the file system or to a snapshot of your live data,
|
||||
you can look directly at the files. To do that, access your `assets` directory
|
||||
which will either be located in your project root or under the `public`
|
||||
directory. The assets directory will contain an hidden `.protected` directory
|
||||
which contains restricted and draft files. Other files which are not stored
|
||||
under the `.protected` directory will be visible to anonymous users. If you can
|
||||
see files that are meant to be confidential outside of the `.protected` folder,
|
||||
then they are accessible by the general public.
|
||||
|
||||
Some files may be stored under a _hash path_. This means that the physical files
|
||||
will be stored in a folder with a 10 character hexadecimal name. e.g.: If your
|
||||
File is stored under `secret/folder/condfidential.pdf` in the CMS, the physical
|
||||
file might be stored under a path similar to
|
||||
`public/assets/secret/folder/c0f7cbd745/condfidential.pdf`.
|
||||
|
||||
[Learn what's the difference between _natural paths_ and _hash paths_](https://docs.silverstripe.org/en/4/developer_guides/files/file_migration/#natural-path-vs-hash-path)
|
||||
on the Silverstripe CMS documentation.
|
||||
|
||||
Alternatively, you can try accessing the file directly in a incognito/private
|
||||
browser session. To do so, navigate to a restricted file in the asset
|
||||
administration interface inside the CMS. On the right-hand panel,
|
||||
right-click on the file preview and copy the link to the file. If you paste the
|
||||
link into a private/incognito browser session and can access the file, then your
|
||||
file can be viewed by the general public.
|
||||
|
||||
## Running the migration tasks
|
||||
|
||||
The 4.4.6/4.5.2 Silverstripe CMS releases add new file migration subtasks to
|
||||
retroactively protect files that have been wrongly exposed. They are 3 new
|
||||
subtasks.
|
||||
|
||||
* `migrate-folders` creates versioning metadata for Silverstripe CMS 3 Folder
|
||||
records.
|
||||
* `normalise-access` protect files that have been wrongly exposed.
|
||||
* `relocate-userform-uploads-2020-9280` move files uploaded through the
|
||||
userforms module to their intended folder.
|
||||
|
||||
### Do I need to run the migration tasks?
|
||||
|
||||
Based on the nature of your Silverstripe CMS project, you may need to run all of
|
||||
the tasks, some of the them, or none of them.
|
||||
|
||||
You do not need to run any of the subtasks if the following three conditions are
|
||||
all true:
|
||||
* your project was not migrated from Silverstripe CMS 3
|
||||
* your project does not include the userforms module, or if it does, no userform
|
||||
has been configured to allow file uploads
|
||||
* your project does not programmatically create files or allow users to upload
|
||||
files via a custom form(s).
|
||||
|
||||
If your project was upgraded from a Silverstripe CMS 3 project, you should
|
||||
minimally run the `migrate-folders` subtask.
|
||||
|
||||
If your project programmatically creates files or allows users to upload files
|
||||
via a user form or a custom form, you should run the `normalise-access` task.
|
||||
|
||||
If your project allows users to upload files via a user form and was upgraded from
|
||||
a Silverstripe CMS 3 project, you may need to run all 3 tasks.
|
||||
|
||||
If your project was migrated from Silverstripe CMS 3 and allows users to upload
|
||||
files via custom forms, you should run the `migrate-folders` subtask. However,
|
||||
you also will need to manually protect the affected files. The easiest way
|
||||
could be to find all the folders affected through a SQL query before you run the
|
||||
task. Then you may be able to find all the custom forms using those folder IDs
|
||||
accordingly. Unfortunately, we cannot provide any automation for this scenario.
|
||||
|
||||
You should also consider making your `/Uploads` folder protected manually
|
||||
(via CMS) as a best practice, since it is publicly accessible by default.
|
||||
|
||||
### What do the migration tasks do?
|
||||
|
||||
Take some time to read the following descriptions and understand how running
|
||||
each subtask will affect your Silverstripe CMS project. `migrate-folders` and
|
||||
`normalise-access` are relatively quick and have no side affects.
|
||||
|
||||
`relocate-userform-uploads-2020-9280` is the most complex of the three subtasks
|
||||
and has the most potential side effects. You should take special care to
|
||||
understand what it does before running it.
|
||||
|
||||
#### migrate-folders subtask
|
||||
|
||||
The `migrate-folders` subtask validates that every "Folder" record in the
|
||||
`File` table has a matching entry in the `File_Live` table. This will prevent
|
||||
future file uploads from being accidentally stored in the publicly accessible
|
||||
"Uploads" folder.
|
||||
|
||||
It does not retroactively move files that have been stored in the wrong Folder
|
||||
to their intended destination.
|
||||
|
||||
To find out what Folders on your Silverstripe CMS project will be affected by
|
||||
running the `migrate-folders` subtask, you can run the following SQL query:
|
||||
|
||||
```sql
|
||||
-- This query is targeted to MySQL. You may need to adapt it for other SQL databases.
|
||||
SELECT
|
||||
File.ID,
|
||||
File.Name
|
||||
FROM
|
||||
File
|
||||
LEFT JOIN
|
||||
File_Live
|
||||
ON File_Live.ID = File.ID
|
||||
WHERE
|
||||
File_Live.ID IS NULL
|
||||
AND File.ClassName = 'SilverStripe\\Assets\\Folder'
|
||||
```
|
||||
|
||||
Note that the file migration task will now run this step by default, so you
|
||||
won't need to explicitly run the `migrate-folders` task for future
|
||||
Silverstripe CMS 3 upgrades.
|
||||
|
||||
[Learn how to migrate files from Silverstripe CMS 3 to Silverstripe CMS 4](https://docs.silverstripe.org/en/4/developer_guides/files/file_migration/#migration-from-silverstripe-3-to-silverstripe-4-4-or-later)
|
||||
on the Silverstripe CMS documentation.
|
||||
|
||||
#### normalise-access subtask
|
||||
|
||||
The `normalise-access` subtask goes through each individual File record in a
|
||||
Silverstripe CMS project and confirms that the `canView` result for anonymous
|
||||
users matches the physical location of the file. If the physical file is
|
||||
publicly visible while it's `canView` method returns `false` for anonymous
|
||||
users, it will be moved to the protected location.
|
||||
|
||||
#### relocate-userform-uploads-2020-9280 task
|
||||
|
||||
Because of the `CVE-2020-9280` vulnerability, you may have Folders without a
|
||||
matching entries in their "Live" table. User form file upload submissions
|
||||
may end up being stored in an incorrect publicly-accessible location under the
|
||||
following conditions:
|
||||
* you have user forms that accept file uploads
|
||||
* the file upload field is configured to save the file in a folder that was
|
||||
created in Silverstripe CMS 3
|
||||
* the targeted folder has not been manually saved since your Silverstripe CMS 4
|
||||
upgrade.
|
||||
|
||||
If those 3 conditions are met, you should consider running the
|
||||
`relocate-userform-uploads-2020-9280` subtask.
|
||||
|
||||
`relocate-userform-uploads-2020-9280` will go through each user form file upload
|
||||
submission and verify that the uploaded file is stored in the folder specified
|
||||
in the matching file upload user form field. If the file is stored in the wrong
|
||||
folder, the task will move the file to the Folder specified in the user form
|
||||
upload field configuration at the time the file was uploaded.
|
||||
|
||||
##### What if I have a custom upload form?
|
||||
|
||||
If you have a written a controller operating in the "Live" stage that creates
|
||||
files or receives uploaded files, and that controller is configured to save
|
||||
files in a folder created in Siverstripe CMS 3, your files may have been stored
|
||||
in the wrong location. Unfortunately, we can not provide a migration task for
|
||||
each custom scenario.
|
||||
|
||||
The `relocate-userform-uploads-2020-9280` only works because there's a record of
|
||||
where the file was meant to be uploaded on the user form page.
|
||||
|
||||
If you have a small number of files, it might be practical to manually update
|
||||
their location via the asset administration interface in the CMS. Otherwise, you
|
||||
may have to write your own migration task to achieve the same purpose.
|
||||
|
||||
### How do I run the migration tasks?
|
||||
|
||||
`migrate-folders`, `normalise-access` and `relocate-userform-uploads-2020-9280`
|
||||
have been written as subtasks of the regular file migration task. The file
|
||||
migration task can be run in 3 different ways:
|
||||
* in the browser under `dev/tasks`
|
||||
* on the command line
|
||||
* as a queued job.
|
||||
|
||||
You can run each subtask individually or you can run all three subtasks in one
|
||||
go. The `only` parameter controls which subtasks will be run. You can get
|
||||
multiple subtask to run by specifying them as a comma-separated list:
|
||||
`only=migrate-folders,normalise-access,relocate-userform-uploads-2020-9280`. The subtasks
|
||||
are executed in a pre-defined sequence, so the order they appeared in the
|
||||
comma-separated list is irrelevant.
|
||||
|
||||
Which ever way you choose to run the sub tasks, you **MUST run `migrate-folders`
|
||||
before `relocate-userform-uploads-2020-9280`**. The recommended order to run the subtasks
|
||||
is:
|
||||
1. `migrate-folders`
|
||||
2. `normalise-access`
|
||||
3. `relocate-userform-uploads-2020-9280`.
|
||||
|
||||
[Learn more about the File Migration Task on the Silverstripe CMS documentation](https://docs.silverstripe.org/en/4/developer_guides/files/file_migration/)
|
||||
|
||||
#### Testing the file migration task first
|
||||
|
||||
If possible, you should consider running the task in a development or testing
|
||||
environment first, either on a snapshot of your production environment or on a
|
||||
subset of your live data. Make sure you have back ups configured on your
|
||||
production environment and a recovery strategy in place in case things go badly.
|
||||
|
||||
#### Running the task in the browser
|
||||
|
||||
Running the file migration task in the browser should only be considered if you
|
||||
have a small number of files. It is susceptible to timeout if the task runs for
|
||||
too long. Depending on your application settings, you may not have the output
|
||||
logs of the tasks run. Please consider the other options first.
|
||||
|
||||
To run the task in the browser, navigate to `/dev/tasks/MigrateFileTask` and
|
||||
provide the `only` parameter as a GET parameter on your request. e.g.:
|
||||
`https://example.com/dev/tasks/MigrateFileTask?only=migrate-folders`
|
||||
|
||||
If you're running this task on a production environment, you will be asked to
|
||||
login using administrator credentials and you will be prompted to confirm you
|
||||
want to execute the task.
|
||||
|
||||
#### Running the task on the command line
|
||||
|
||||
Navigate to your project root on the command line and use the sake utility to
|
||||
execute the `MigrateFileTask` command.
|
||||
|
||||
```bash
|
||||
./vendor/bin/sake dev/tasks/MigrateFileTask only=migrate-folders
|
||||
```
|
||||
|
||||
[Learn how to execute Silverstripe CMS tasks on the command line](https://docs.silverstripe.org/en/4/developer_guides/cli/)
|
||||
|
||||
#### Running the task as a queued job
|
||||
|
||||
If you've installed the
|
||||
[queued-jobs module](https://github.com/symbiote/silverstripe-queuedjobs) on
|
||||
your Silverstripe CMS project, you can run the file migration task as a queued
|
||||
job. There are two alternative ways to schedule a task to run as a queued job:
|
||||
* by navigating to the task URL in your browser (e.g.:
|
||||
`https://example.com/dev/tasks/queue/MigrateFileTask?only=migrate-folders`)
|
||||
* via the command line (e.g.
|
||||
`vendor/bin/sake dev/tasks/queue/MigrateFileTask only=migrate-folders`).
|
||||
|
||||
Once the task has been scheduled, you can monitor its progress in the queued job
|
||||
administration area inside the CMS.
|
||||
|
||||
### How long should I expect the migration tasks to run for?
|
||||
|
||||
#### migrate-folders
|
||||
|
||||
The main factor in the execution time of the `migrate-folders` subtask is the
|
||||
number of Folders to migrate.
|
||||
|
||||
This subtask does not perform any filesystem operations. It mostly performs read
|
||||
and write SQL queries.
|
||||
|
||||
You can expect 20 to 30 Folders to be migrated per second. A project with
|
||||
10,000 Folders to migrate should take less than 10 minutes.
|
||||
|
||||
#### normalise-access
|
||||
|
||||
The main factor in the execution time of the `normalise-access` subtask are:
|
||||
* the number of files to protect
|
||||
* the number of files in the same folder.
|
||||
|
||||
Protecting 1000 folders with 1 file each will be considerably faster than 1
|
||||
folder with 1000 files. The total number of files in your project will also
|
||||
impact the subtask runtime, but to a lesser extent.
|
||||
|
||||
This substask performs a lot of file system operations with some read SQL
|
||||
queries. It does not write data to the database.
|
||||
|
||||
You can expect 10 to 20 files to be protected per seconds. Performance is
|
||||
degraded if all those files are in a small number of folders.
|
||||
|
||||
* A project with 10,000 files to protected spread through a lot of folders
|
||||
should take less than an hour.
|
||||
* A project with 10,000 files to protected all in one folder can take several
|
||||
hours.
|
||||
|
||||
#### relocate-userform-uploads-2020-9280
|
||||
|
||||
The main factor in the execution time of the `normalise-access` subtask are:
|
||||
* the number of files to protect
|
||||
* the number of files in the same folder.
|
||||
|
||||
Moving 1000 folders with 1 file each will be considerably faster than 1 folder
|
||||
with 1000 files.
|
||||
|
||||
This substask performs a mix of file system operations and read/write SQL
|
||||
queries.
|
||||
|
||||
The approximate speed of the task is:
|
||||
- 500 files per minute with 1k files in the same folder (9 files per second)
|
||||
- 60 files per minute with 10k files in the same folder (1 file per second).
|
||||
|
||||
## Edges cases and potential "gotchas"
|
||||
|
||||
### I don't have "/Uploads" folder in CMS
|
||||
|
||||
Either the default "Uploads" folder was changed via
|
||||
[Silverstripe\Assets\Upload::uploads_folder](https://api.silverstripe.org/4/SilverStripe/Assets/Upload.html)
|
||||
configuration parameter, or you don't have any files uploaded to it.
|
||||
|
||||
The issues covered by this patch may still affect your application.
|
||||
|
||||
### I have two "/Uploads" folders in CMS
|
||||
If you see two /Uploads folders in CMS, most likely that means one of them was
|
||||
migrated from Silverstripe CMS 3, whereas some application logic created the
|
||||
second copy after the migration.
|
||||
|
||||
In that case your database would contain a record in the `File` table for each
|
||||
of them, while `File_Live` table would only have a record about the other one.
|
||||
|
||||
After running the tasks provided in this patch, we suggest you manually move all
|
||||
content from one Folder to the other via the CMS. Then remove the empty folder.
|
||||
|
||||
### What if I updated my files after upload?
|
||||
|
||||
Beware that draft files are present in 2 locations on the filesystem.
|
||||
|
||||
* The original live version of the file is still available.
|
||||
* The draft version of the file should be present in a `.protected` folder that
|
||||
is inaccessible for unauthenticated users.
|
||||
|
||||
This means that even if you moved a file but don't publish it, the live version
|
||||
of the file will still be available.
|
||||
|
||||
To address this, "relocate-userform-uploads-2020-9280" task only works on the
|
||||
very first version of a file if it's published. Subsequent versions of the file
|
||||
are ignored by the task. For example, even if you didn't change the location of
|
||||
a file, but updated the filename or its permissions, the script will ignore that
|
||||
file.
|
||||
|
||||
If you have an unpublished draft, but the live version of the file is 1 (no
|
||||
published changes after upload), the script will try to move the live version of
|
||||
the file into its originally intended location, while preserving the current
|
||||
draft version of the file as-is. This would increment numbers for both Live and
|
||||
Draft versions of the file, while moving the live version to another location
|
||||
(both on the file system and in the CMS).
|
||||
|
||||
### Files with draft access restriction
|
||||
|
||||
If you have a published file that is publicly available and you update the draft
|
||||
version to restrict read access, the live file currently remains accessible
|
||||
until you publish the draft version. However, the `canView` method on the live
|
||||
file will immediately start returning `false` for anonymous users.
|
||||
|
||||
This will cause `normalise-access` to protect the live file. Beware that if
|
||||
you have unpublished access restrictions on draft files, those will take effect
|
||||
on the live file after running `normalise-access`.
|
||||
|
||||
Read the ["Files with access restriction in Draft" GitHub issue](https://github.com/silverstripe/silverstripe-assets/issues/385)
|
||||
for more details.
|
||||
|
||||
<!--- Changes below this line will be automatically regenerated -->
|
||||
|
||||
## Change Log
|
||||
|
||||
### Bugfixes
|
||||
|
||||
* 2020-03-09 [c4709b6](https://github.com/silverstripe/silverstripe-assets/commit/c4709b6c6af840ea618b36d8ffe76f1ed48a21b3) Add FolderMigrationHelper
|
||||
* 2020-03-08 [9779e4296](https://github.com/silverstripe/silverstripe-framework/commit/9779e42963031a0fed2ed01fc3b8e470d1114723) Register new sub tasks to fix files affected by CVE-2020-9280 and CVE-2019-12245 (Serge Latyntcev)
|
||||
* 2020-03-04 [89e69ad](https://github.com/silverstripe/silverstripe-assets/commit/89e69ad3b06072dc841d081c36063475e39df4f9) Create NormaliseAccessMigrationHelper to fix files affected by CVE-2019-12245 (Maxime Rainville)
|
||||
<!--- Changes above this line will be automatically regenerated -->
|
@ -9,6 +9,8 @@ use Psr\Log\LoggerInterface;
|
||||
use SilverStripe\AssetAdmin\Helper\ImageThumbnailHelper;
|
||||
use SilverStripe\Assets\Dev\Tasks\LegacyThumbnailMigrationHelper;
|
||||
use SilverStripe\Assets\Dev\Tasks\FileMigrationHelper;
|
||||
use SilverStripe\Assets\Dev\Tasks\FolderMigrationHelper;
|
||||
use SilverStripe\Assets\Dev\Tasks\NormaliseAccessMigrationHelper;
|
||||
use SilverStripe\Assets\Storage\AssetStore;
|
||||
use SilverStripe\Assets\Storage\FileHashingService;
|
||||
use SilverStripe\Control\Director;
|
||||
@ -17,6 +19,7 @@ use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\Logging\PreformattedEchoHandler;
|
||||
use SilverStripe\Dev\BuildTask;
|
||||
use SilverStripe\Assets\Dev\Tasks\SecureAssetsMigrationHelper;
|
||||
use SilverStripe\UserForms\Task\RecoverUploadLocationsHelper;
|
||||
use \Bramus\Monolog\Formatter\ColoredLineFormatter;
|
||||
|
||||
/**
|
||||
@ -30,12 +33,18 @@ class MigrateFileTask extends BuildTask
|
||||
|
||||
protected $defaultSubtasks = [
|
||||
'move-files',
|
||||
'migrate-folders',
|
||||
'move-thumbnails',
|
||||
'generate-cms-thumbnails',
|
||||
'fix-folder-permissions',
|
||||
'fix-secureassets',
|
||||
];
|
||||
|
||||
protected $optInSubtasks = [
|
||||
'normalise-access',
|
||||
'relocate-userform-uploads-2020-9280'
|
||||
];
|
||||
|
||||
private static $dependencies = [
|
||||
'logger' => '%$' . LoggerInterface::class,
|
||||
];
|
||||
@ -81,13 +90,24 @@ class MigrateFileTask extends BuildTask
|
||||
->setLogger($this->logger)
|
||||
->run();
|
||||
|
||||
// TODO Split file migration helper into two tasks,
|
||||
// and report back on their process counts consistently here
|
||||
// if ($count) {
|
||||
// $this->logger->info("{$count} File objects upgraded");
|
||||
// } else {
|
||||
// $this->logger->info("No File objects needed upgrading");
|
||||
// }
|
||||
$this->extend('postFileMigrationSubtask', $subtask);
|
||||
}
|
||||
}
|
||||
|
||||
$subtask = 'migrate-folders';
|
||||
if (in_array($subtask, $subtasks)) {
|
||||
if (!class_exists(FolderMigrationHelper::class)) {
|
||||
$this->logger->error("No folder migration helper detected");
|
||||
} else {
|
||||
$this->extend('preFileMigrationSubtask', $subtask);
|
||||
|
||||
$this->logger->notice("######################################################");
|
||||
$this->logger->notice("Migrating folder database records ({$subtask})");
|
||||
$this->logger->notice("######################################################");
|
||||
|
||||
FolderMigrationHelper::singleton()
|
||||
->setLogger($this->logger)
|
||||
->run();
|
||||
|
||||
$this->extend('postFileMigrationSubtask', $subtask);
|
||||
}
|
||||
@ -195,6 +215,44 @@ class MigrateFileTask extends BuildTask
|
||||
}
|
||||
}
|
||||
|
||||
$subtask = 'normalise-access';
|
||||
if (in_array($subtask, $subtasks)) {
|
||||
if (!class_exists(NormaliseAccessMigrationHelper::class)) {
|
||||
$this->logger->error("No normalise access migration helper detected");
|
||||
} else {
|
||||
$this->extend('preFileMigrationSubtask', $subtask);
|
||||
|
||||
$this->logger->notice("######################################################");
|
||||
$this->logger->notice("Migrating filesystem and database records ({$subtask})");
|
||||
$this->logger->notice("######################################################");
|
||||
|
||||
NormaliseAccessMigrationHelper::singleton()
|
||||
->setLogger($this->logger)
|
||||
->run();
|
||||
|
||||
$this->extend('postFileMigrationSubtask', $subtask);
|
||||
}
|
||||
}
|
||||
|
||||
$subtask = 'relocate-userform-uploads-2020-9280';
|
||||
if (in_array($subtask, $subtasks)) {
|
||||
if (!class_exists(RecoverUploadLocationsHelper::class)) {
|
||||
$this->logger->error("No UserForms helper detected");
|
||||
} else {
|
||||
$this->extend('preFileMigrationSubtask', $subtask);
|
||||
|
||||
$this->logger->notice("######################################################");
|
||||
$this->logger->notice("Recovering UserForm uploaded file locations ({$subtask})");
|
||||
$this->logger->notice("######################################################");
|
||||
|
||||
RecoverUploadLocationsHelper::singleton()
|
||||
->setLogger($this->logger)
|
||||
->run();
|
||||
|
||||
$this->extend('postFileMigrationSubtask', $subtask);
|
||||
}
|
||||
}
|
||||
|
||||
$this->extend('postFileMigration');
|
||||
|
||||
$this->logger->info("Done!");
|
||||
@ -236,8 +294,13 @@ TXT;
|
||||
protected function validateArgs($args)
|
||||
{
|
||||
if (!empty($args['only'])) {
|
||||
if (array_diff(explode(',', $args['only']), $this->defaultSubtasks)) {
|
||||
throw new \InvalidArgumentException('Invalid subtasks detected: ' . $args['only']);
|
||||
$only = explode(',', $args['only']);
|
||||
|
||||
$diff = array_diff($only, $this->defaultSubtasks);
|
||||
$diff = array_diff($diff, $this->optInSubtasks);
|
||||
|
||||
if ($diff) {
|
||||
throw new \InvalidArgumentException('Invalid subtasks detected: ' . implode(', ', $diff));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user