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

feat(server): add support for multiple auth tokens via env vars #339

Merged
merged 4 commits into from
Aug 24, 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
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -280,16 +280,21 @@ If the configuration file is not found in the current directory, specify it via
$ CONFIG="$HOME/.rustypaste.toml" rustypaste
```

#### Authentication

To enable basic HTTP auth, set the `AUTH_TOKEN` environment variable (via `.env`):

```sh
$ echo "AUTH_TOKEN=$(openssl rand -base64 16)" > .env
$ rustypaste
```

You can also set multiple auth tokens via the array field `[server].auth_tokens` in your `config.toml`.
There are 2 options for setting multiple auth tokens:

- Via the array field `[server].auth_tokens` in your `config.toml`.
- Or by writing a newline separated list to a file and passing its path to rustypaste via `AUTH_TOKENS_FILE` and `DELETE_TOKENS_FILE` respectively.

> If neither `AUTH_TOKEN` nor `[server].auth_tokens` are set, the server will not require any authentication.
> If neither `AUTH_TOKEN`, `AUTH_TOKENS_FILE` nor `[server].auth_tokens` are set, the server will not require any authentication.
>
> Exception is the `DELETE` endpoint, which requires at least one token to be set. See [deleting files from server](#delete-file-from-server) for more information.

Expand Down
7 changes: 6 additions & 1 deletion fixtures/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ This directory contains the [test fixtures](https://en.wikipedia.org/wiki/Test_f
1. Build the project in debug mode: `cargo build`
2. Execute the runner script in this directory: `./test-fixtures.sh`

On `macOS` you need to have [coreutils](https://www.gnu.org/software/coreutils/) installed to run the script.
On `macOS` you need to have [coreutils](https://www.gnu.org/software/coreutils/) installed to run the script.
The simplest way is to install it via [Homebrew](https://brew.sh/): `brew install coreutils`

### Adding new fixtures
Expand All @@ -28,6 +28,11 @@ test-file-upload/
```sh
#!/usr/bin/env bash

# Optional
custom_env() {
# setting environment variables such as AUTH_TOKEN or AUTH_TOKENS_FILE
}

setup() {
# preparation
}
Expand Down
4 changes: 2 additions & 2 deletions fixtures/test-expiring-file-upload/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
content="test data"

setup() {
echo "$content" > file
echo "$content" >file
}

run_test() {
file_url=$(curl -s -F "file=@file" -H "expire:1s" localhost:8000)
test "$content" = "$(cat upload/file.txt.*)"
sleep 2
sleep 3

result="$(curl -s $file_url)"
test "file is not found or expired :(" = "$result"
Expand Down
8 changes: 6 additions & 2 deletions fixtures/test-fixtures.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ NC='\033[0m'
run_fixture() {
cd "$FIXTURE_DIR/$1" || exit 1
source "test.sh"
type custom_env &>/dev/null && custom_env
NO_COLOR=1 CONFIG=config.toml "$PROJECT_DIR/target/debug/rustypaste" &
SERVER_PID=$!
trap 'kill -9 "$SERVER_PID" && wait "$SERVER_PID" 2> /dev/null' RETURN
sleep 1
( set -e;
(
set -e
setup
run_test
teardown
Expand All @@ -24,7 +26,9 @@ run_fixture() {

main() {
find * -maxdepth 0 -type d -print0 | while IFS= read -r -d '' fixture; do
run_fixture "$fixture"
# Since we are creating a subshell, all environment variables created by custom_env will be lost
# Return code is preserved
(run_fixture "$fixture")
exit_status=$?
if [ "$exit_status" -eq 0 ]; then
echo -e "[${GREEN}ok${NC}] $fixture"
Expand Down
4 changes: 4 additions & 0 deletions fixtures/test-server-auth-token-file/auth_file
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
bread
brioche
baguette
naan
8 changes: 8 additions & 0 deletions fixtures/test-server-auth-token-file/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[server]
address = "127.0.0.1:8000"
max_content_length = "10MB"
upload_path = "./upload"

[paste]
default_extension = "txt"
duplicate_files = false
38 changes: 38 additions & 0 deletions fixtures/test-server-auth-token-file/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#!/usr/bin/env bash

content1="test data"
content2="other test"

custom_env() {
export AUTH_TOKENS_FILE=./auth_file
}

setup() {
echo "$content1" >file1
echo "$content2" >file2
}

run_test() {
file_url=$(curl -s -F "file=@file1" -H "Authorization: bread" localhost:8000)
test "$content1" = "$(cat upload/file1.txt)"
sleep 2

result="$(curl -s $file_url)"
test "$content1" = "$result"

file_url=$(curl -s -F "file=@file2" -H "Authorization: naan" localhost:8000)
test "$content2" = "$(cat upload/file2.txt)"
sleep 2

result="$(curl -s $file_url)"
test "$content2" = "$result"

result=$(curl -s -F "file=@file2" -H "Authorization: tomato" localhost:8000)
test "$result" = "unauthorized"
}

teardown() {
rm file1
rm file2
rm -r upload
}
8 changes: 8 additions & 0 deletions fixtures/test-server-delete-token-file/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[server]
address = "127.0.0.1:8000"
max_content_length = "10MB"
upload_path = "./upload"

[paste]
default_extension = "txt"
duplicate_files = false
4 changes: 4 additions & 0 deletions fixtures/test-server-delete-token-file/delete_file
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
bread
brioche
baguette
naan
29 changes: 29 additions & 0 deletions fixtures/test-server-delete-token-file/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/env bash

content1="test data"
del_resp="file deleted"

custom_env() {
export DELETE_TOKENS_FILE=./delete_file
}

setup() {
echo "$content" >file
}

run_test() {
file_url=$(curl -s -F "file=@file" localhost:8000)
test "$del_rep"="$(curl -s -H "Authorization: naan" -X DELETE $file_url)"

sleep 2
file_url=$(curl -s -F "file=@file" localhost:8000)
test "$del_re"="$(curl -s -H "Authorization: bread" -X DELETE $file_url)"

file_url=$(curl -s -F "file=@file" localhost:8000)
test "unauthorized"=$(curl -s -H "Authorization: tomato" -X DELETE $file_url)
}

teardown() {
rm file
rm -r upload
}
32 changes: 31 additions & 1 deletion src/config.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use crate::mime::MimeMatcher;
use crate::random::RandomURLConfig;
use crate::{AUTH_TOKEN_ENV, DELETE_TOKEN_ENV};
use crate::{AUTH_TOKENS_FILE_ENV, AUTH_TOKEN_ENV, DELETE_TOKENS_FILE_ENV, DELETE_TOKEN_ENV};
use byte_unit::Byte;
use config::{self, ConfigError};
use std::collections::HashSet;
use std::env;
use std::fs::read_to_string;
use std::path::{Path, PathBuf};
use std::time::Duration;

Expand Down Expand Up @@ -162,6 +163,21 @@ impl Config {
if let Ok(env_token) = env::var(AUTH_TOKEN_ENV) {
tokens.insert(env_token);
}
if let Ok(env_path) = env::var(AUTH_TOKENS_FILE_ENV) {
match read_to_string(&env_path) {
Ok(s) => {
s.lines().filter(|l| !l.trim().is_empty()).for_each(|l| {
tokens.insert(l.to_string());
});
}
Err(e) => {
error!(
"failed to read tokens from authentication file ({env_path}) ({e})"
);
}
};
}

tokens
}
TokenType::Delete => {
Expand All @@ -170,6 +186,20 @@ impl Config {
if let Ok(env_token) = env::var(DELETE_TOKEN_ENV) {
tokens.insert(env_token);
}

if let Ok(env_path) = env::var(DELETE_TOKENS_FILE_ENV) {
match read_to_string(&env_path) {
Ok(s) => {
s.lines().filter(|l| !l.trim().is_empty()).for_each(|l| {
tokens.insert(l.to_string());
});
}
Err(e) => {
error!("failed to read deletion tokens from file ({env_path}) ({e})");
}
};
}

tokens
}
};
Expand Down
6 changes: 6 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,11 @@ pub const CONFIG_ENV: &str = "CONFIG";
/// Environment variable for setting the authentication token.
pub const AUTH_TOKEN_ENV: &str = "AUTH_TOKEN";

/// Environment variable for the path to a file containing multiple authentication token.
pub const AUTH_TOKENS_FILE_ENV: &str = "AUTH_TOKENS_FILE";

/// Environment variable for setting the deletion token.
pub const DELETE_TOKEN_ENV: &str = "DELETE_TOKEN";

/// Environment variable for the path to a file containing multiple deletion token.
pub const DELETE_TOKENS_FILE_ENV: &str = "DELETE_TOKENS_FILE";
Loading