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

Updated authorization logic #47

Merged
merged 5 commits into from
Nov 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
Note: Numbers like (#123) point to closed Pull Requests on the fractal-vizarr-viewer repository.

# Unreleased

* Distinguished handling of 401 Unauthorized and 403 Forbidden responses (\#47);
* Included `user_settings.project_dir` in list of allowed paths (\#47);
* Supported `AUTHORIZATION_SCHEME="testing-basic-auth"` (\#47);

# 0.2.1

* Updated Vizarr git commit references and removed vizarr.patch (\#42);
Expand Down
19 changes: 10 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,9 @@ To start the application installed in this way see the section [Run fractal-viza
* `VIZARR_STATIC_FILES_PATH`: path to the files generated running `npm run build` in vizarr source folder;
* `BASE_PATH`: base path of fractal-vizarr-viewer application;
* `AUTHORIZATION_SCHEME`: defines how the service verifies user authorization. The following options are available:
* `fractal-server-viewer-paths`: the paths that can be accessed by each user are retrieved calling fractal-server API;
* `fractal-server-viewer-paths`: the paths that can be accessed by each user are retrieved calling fractal-server API.
* `user-folders`: each registered user can only access their own folder, which corresponds to a directory under `ZARR_DATA_BASE_PATH` named as their `slurm_user` field.
* `testing-basic-auth`: enables Basic Authentication for testing purposes. The credentials are specified through two additional environment variables: `TESTING_USERNAME` and `TESTING_PASSWORD`. This option should not be used in production environments.
* `none`: no authorization checks are performed, allowing access to all users, including anonymous ones. This option is useful for demonstrations and testing but should not be used in production environments.
* `CACHE_EXPIRATION_TIME`: cookie cache TTL in seconds; when user info is retrieved from a cookie calling the current user endpoint on fractal-server the information is cached for the specified amount of seconds, to reduce the number of calls to fractal-server;
* `LOG_LEVEL_CONSOLE`: the log level of logs that will be written to the console; the default value is `info`;
Expand Down Expand Up @@ -199,21 +200,21 @@ Then go back to fractal-vizarr-viewer folder and run `npm run start` to start th

## Docker setup

Build the docker image:
The following script can be used to build and start a docker image for testing:

```sh
docker build . -t fractal-vizarr-viewer
```
#!/bin/sh

The following command can be used to start the docker image for testing:
COMMIT_HASH=$(git rev-parse HEAD)
IMAGE_NAME="fractal-vizarr-viewer-$COMMIT_HASH"

docker build . -t "$IMAGE_NAME"

```sh
docker run --network host \
-v /path/to/zarr-files:/zarr-files \
-e ZARR_DATA_BASE_PATH=/zarr-files \
-v /tmp/zarr-files:/zarr-files \
-e FRACTAL_SERVER_URL=http://localhost:8000 \
-e AUTHORIZATION_SCHEME=fractal-server-viewer-paths \
fractal-vizarr-viewer
"$IMAGE_NAME"
```

For production replace the `--network host` option with a proper published port `-p 3000:3000` and set `FRACTAL_SERVER_URL` as an URL using a public domain.
41 changes: 13 additions & 28 deletions src/app.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import express from 'express';
import * as fs from 'fs';
import { getLogger } from './logger.js';
import { getConfig } from './config.js';
import { getAuthorizer } from './authorizer.js';
import express from "express";
import { getLogger } from "./logger.js";
import { getConfig } from "./config.js";
import { serveZarrData } from "./data.js";
import { getAuthorizer } from "./authorizer.js";

const config = getConfig();
const logger = getLogger();
Expand All @@ -20,39 +20,24 @@ const authorizer = getAuthorizer();

// Endpoint serving zarr files
app.use(`${config.basePath}data`, async function (req, res) {
try {
const authorizedPath = await authorizer.getAuthorizedPath(req);
if (!authorizedPath) {
logger.info("Forbidden request: %s", req.path.normalize());
return res.status(403).send('Forbidden').end();
}
if (!fs.existsSync(authorizedPath)) {
logger.info("File not found: %s", authorizedPath);
return res.status(404).send('Not Found').end();
}
if (fs.lstatSync(authorizedPath).isDirectory()) {
logger.info("Path is directory: %s", authorizedPath);
return res.status(400).send('Is directory').end();
}
const stream = fs.createReadStream(authorizedPath);
stream.pipe(res);
} catch (err) {
logger.error('Error reading file', err);
return res.status(500).send('Internal Server Error').end();
}
await serveZarrData(authorizer, req, res);
});

// Serving Vizarr static files
app.use(`${config.basePath}`, express.static(config.vizarrStaticFilesPath));

// Start server
const server = app.listen(config.port, () => {
logger.info('fractal-vizarr-viewer is listening at http://localhost:%d%s', config.port, config.basePath)
logger.info(
"fractal-vizarr-viewer is listening at http://localhost:%d%s",
config.port,
config.basePath
);
});

for (const signal of ['SIGINT', 'SIGTERM', 'SIGQUIT']) {
for (const signal of ["SIGINT", "SIGTERM", "SIGQUIT"]) {
process.on(signal, (signal) => {
logger.info('Process received a %s signal', signal);
logger.info("Process received a %s signal", signal);
server.close();
});
}
Loading