Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set up a php oc10 controller for reading the config.json from the config folder #4537

Merged
merged 17 commits into from
Jan 5, 2021

Conversation

kulmann
Copy link
Member

@kulmann kulmann commented Dec 17, 2020

Description

When ownCloud Web is deployed as an app, we need to read the config from the config folder, instead of from within the app folder. Otherwise we'll have issues with the signing.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Technical debt
  • Tests

Checklist:

  • Code changes
  • Unit tests added
  • Acceptance tests added
  • Documentation ticket raised:

@update-docs

This comment has been minimized.

@kulmann kulmann self-assigned this Dec 17, 2020
@kulmann kulmann marked this pull request as draft December 17, 2020 16:15
@CLAassistant
Copy link

CLAassistant commented Dec 17, 2020

CLA assistant check
All committers have signed the CLA.

@kulmann
Copy link
Member Author

kulmann commented Dec 18, 2020

FYI, I discovered that while the app is reachable from a route with apps-external in it, the controller endpoint is only reachable from <baseurl>/index.php/apps/web/config, not <baseurl>/index.php/apps-external/web/config. This is - thanks @IljaN for pointing that out - because the app itself is served directly from it's path by the webserver. Not by the oc10 app framework. We might run into issues with that. Another solution would be to have a controller in place that serves all the static files of the app. But that's very ugly as well.... needs discussion.

@kulmann kulmann changed the title WIP: Set up a php oc10 controller for reading the config.json from the config folder Set up a php oc10 controller for reading the config.json from the config folder Dec 18, 2020
@kulmann kulmann marked this pull request as ready for review December 18, 2020 12:12
@kulmann kulmann requested review from LukasHirt and micbar December 18, 2020 12:12
Copy link
Collaborator

@LukasHirt LukasHirt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually liked it when the config was directly copied as config.json. No need to rename/copy the original file then on the server. But it's not anything critical that I'd try to block the PR with. 😁 LGTM 🚀

@kulmann
Copy link
Member Author

kulmann commented Dec 18, 2020

I actually liked it when the config was directly copied as config.json. No need to rename/copy the original file then on the server. But it's not anything critical that I'd try to block the PR with. 😁 LGTM 🚀

The reason why this is important in this PR is because we first try to load the config.json directly and only if it doesn't exist we try the new oc10 app endpoint. So we really need that it doesn't exist in the first place. 😁

One ugly thing here: for the app deployment we will always have a 404 error for the config.json in the javascript console. The 404 is expected and we react on it by trying the config endpoint. But we can't suppress the console output.

@kulmann kulmann force-pushed the php-config-controller branch from a4696ec to 62f78e1 Compare December 29, 2020 15:20
@micbar
Copy link
Contributor

micbar commented Dec 30, 2020

@C0rby This needs a security review. Can you take a look?

@micbar micbar requested a review from C0rby December 30, 2020 06:35
@kulmann
Copy link
Member Author

kulmann commented Dec 30, 2020

I actually liked it when the config was directly copied as config.json. No need to rename/copy the original file then on the server. But it's not anything critical that I'd try to block the PR with. 😁 LGTM 🚀

The reason why this is important in this PR is because we first try to load the config.json directly and only if it doesn't exist we try the new oc10 app endpoint. So we really need that it doesn't exist in the first place. 😁

One ugly thing here: for the app deployment we will always have a 404 error for the config.json in the javascript console. The 404 is expected and we react on it by trying the config endpoint. But we can't suppress the console output.

This is not true anymore. Instead of relying on the webserver to serve the app, we now have a php controller in place that serves all the files (except for the config.json) of the app. This brings three improvements:

  1. We were now able to change the route for the config, so that it's config.json again and accessed with a require('config.json') call again. No need to construct the php controller route in the js code. No knowledge of the php env in the js code anymore. 🎉 🙌
  2. For configuring the web.baseUrl in config.php, the admin doesn't need to care anymore whether the web app lives in apps, apps-external or some other custom apps folder. The Url always points to apps, as the app framework within core takes care of merging all configured app locations into apps routes.
  3. When the app is disabled, it (properly) doesn't work anymore. Before it was still served from the webserver, so disabling the app didn't have any effect. The only remaining thing is the nav item. So after disabling the app, one still has to remove the web.baseUrl from config.php to remove all traces of the app in the frontend.

@kulmann
Copy link
Member Author

kulmann commented Dec 30, 2020

@C0rby This needs a security review. Can you take a look?

@C0rby
Some context and more detailed questions: we introduced a FilesController which takes care of serving all the files of the web app (js, css, html, ...). Within the controller we have some checks in place - but we would like to have a second opinion of whether this is sufficient:

  1. we don't allow .. in any path so that directory traversals to parent folders outside the app should ™️ not be possible.
  2. we only allow paths and files that start with or equal the content of the permittedPaths array.
  3. we needed to allow inline script execution in CSP headers for the two files oidc-callback.html and oidc-silent-redirect.html, because they are redirecting to different urls via inline script execution. We ran some manual tests if those headers really only apply to those two files - looks like that is the case. But this needs your attention and opinion.
  4. since we're serving the files from the controller, the rules from the .htaccess file don't apply. We applied the headers manually to the response headers.

cc @LukasHirt

Copy link
Contributor

@micbar micbar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let us wait for @C0rby before we merge

@C0rby
Copy link
Contributor

C0rby commented Jan 4, 2021

The code looks good so far but I wanted to try to bypass the path traversal checks.
Unfortunately I can't get it to run... I always get config.json not found but it doesn't seem like the ConfigController.php is called.

@kulmann
Copy link
Member Author

kulmann commented Jan 4, 2021

The code looks good so far but I wanted to try to bypass the path traversal checks.
Unfortunately I can't get it to run... I always get config.json not found but it doesn't seem like the ConfigController.php is called.

Did you copy a config.json into the config path of oc10?

@C0rby
Copy link
Contributor

C0rby commented Jan 4, 2021

Yes, but my error was that I forgot the index.php in the baseUrl... 🤦

Copy link
Contributor

@C0rby C0rby left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good. 👍
You might want to consider what I wrote in the comment but it's not absolutely necessary.

if (\is_dir($path)) {
return new DataResponse(['error' => 'resource not found'], Http::STATUS_NOT_FOUND);
}
$absolutePath = \dirname(__FILE__, 3) . '/' . $path;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The checks look good.
There is one thing I would change though.

$basePath = \dirname(__DIR__,2);
$absolutePath = \realpath( $basePath . '/' . $path;
if ($absolutePath === false) {
  return new DataResponse(['error' => 'resource not found'], Http::STATUS_NOT_FOUND);
}
if (\strpos($absolutePath, $basePath) !== 0) {
  return new DataResponse(['error' => 'resource not found'], Http::STATUS_NOT_FOUND);
}

This way if somehow an attacker manages to do path traversal we still check if the resulting path is in the allowed directory.

@kulmann kulmann requested a review from micbar January 5, 2021 13:58
@kulmann kulmann force-pushed the php-config-controller branch from 5716ef1 to 6d43095 Compare January 5, 2021 14:03
@kulmann kulmann merged commit 13d1b3a into master Jan 5, 2021
@delete-merged-branch delete-merged-branch bot deleted the php-config-controller branch January 5, 2021 16:11
ownclouders pushed a commit that referenced this pull request Jan 5, 2021
Merge: 875dc7c 6d43095
Author: Benedikt Kulmann <[email protected]>
Date:   Tue Jan 5 17:11:35 2021 +0100

    Merge pull request #4537 from owncloud/php-config-controller

    Set up a php oc10 controller for reading the config.json from the config folder
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants