From f276084429f7fee87765e97d313af98d0dc9bbc6 Mon Sep 17 00:00:00 2001 From: Clifton Palmer Date: Sat, 19 Aug 2023 07:40:39 -0500 Subject: [PATCH 1/1] Replaced old perl publish with web-accessible publish - basic auth for all web interfaces now at /lua/ - external docker httpd password directory for security (needs initialization) - html form for submitting publishing patterns --- .env | 2 - .gitignore | 1 + Dockerfile | 5 ++- docker-compose.yml | 8 ++-- httpd.conf | 20 +++++++++- lua/dump_files.lua | 42 ++++++++++++++++++++ lua/publish.lua | 38 ++++++++++++++++++ lua/publish.sh | 22 +++++++++++ lua/submit.html | 24 ++++++++++++ public | 98 ---------------------------------------------- public.sh | 10 ----- readme.md | 18 ++------- 12 files changed, 158 insertions(+), 130 deletions(-) delete mode 100644 .env create mode 100644 lua/dump_files.lua create mode 100644 lua/publish.lua create mode 100755 lua/publish.sh create mode 100644 lua/submit.html delete mode 100755 public delete mode 100755 public.sh diff --git a/.env b/.env deleted file mode 100644 index f9b18d8..0000000 --- a/.env +++ /dev/null @@ -1,2 +0,0 @@ -LOCAL_STORAGE=/mnt/data2/purplebirdman/art -IPV4_WAN=public.purplebirdman.com diff --git a/.gitignore b/.gitignore index 1377554..cba83f7 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ +.env *.swp diff --git a/Dockerfile b/Dockerfile index 0624f65..8659635 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,7 @@ FROM httpd:2.4-alpine +# open htdocs so scripts can write dynamically into there +RUN chmod 777 /usr/local/apache2/htdocs + COPY /httpd.conf /usr/local/apache2/conf/httpd.conf -COPY /public /root/public +COPY /lua /usr/local/apache2/lua diff --git a/docker-compose.yml b/docker-compose.yml index 4fc3c44..e0ed0d7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,16 +2,18 @@ version: '3' services: web: build: . - image: cjpalmer/public:1.1.0 + image: cjpalmer/public:1.2.0 volumes: - - ${LOCAL_STORAGE}:/storage + - ${SHARE_ROOT}:/storage - public_data:/usr/local/apache2/htdocs + - httpd_users:/usr/local/apache2/auth environment: - PUBLIC_ROOT_DIR=/storage - PUBLIC_LINK_DIR=/usr/local/apache2/htdocs - - PUBLIC_HTTP_URI=https://${IPV4_WAN} ports: - 80:80 volumes: public_data: driver: local + httpd_users: + driver: local diff --git a/httpd.conf b/httpd.conf index d7ce626..e2bb8fb 100644 --- a/httpd.conf +++ b/httpd.conf @@ -127,7 +127,7 @@ LoadModule log_config_module modules/mod_log_config.so #LoadModule log_debug_module modules/mod_log_debug.so #LoadModule log_forensic_module modules/mod_log_forensic.so #LoadModule logio_module modules/mod_logio.so -#LoadModule lua_module modules/mod_lua.so +LoadModule lua_module modules/mod_lua.so LoadModule env_module modules/mod_env.so #LoadModule mime_magic_module modules/mod_mime_magic.so #LoadModule cern_meta_module modules/mod_cern_meta.so @@ -229,7 +229,7 @@ Group daemon # e-mailed. This address appears on some server-generated pages, such # as error documents. e.g. admin@your-domain.com # -ServerAdmin purplebirdman@mail.purplebirdman.online +ServerAdmin purplebirdman@purplebirdman.com # # ServerName gives the name and port that the server uses to identify itself. @@ -307,6 +307,11 @@ DocumentRoot "/usr/local/apache2/htdocs" Require all denied +# run lua scripts using ".lua" extension + + SetHandler lua-script + + # # ErrorLog: The location of the error log file. # If you do not specify an ErrorLog directive within a @@ -380,6 +385,7 @@ LogLevel warn # directives as to Alias. # ScriptAlias /cgi-bin/ "/usr/local/apache2/cgi-bin/" + ScriptAlias /lua/ "/usr/local/apache2/lua/" @@ -401,6 +407,16 @@ LogLevel warn Require all granted +# more lua stuff + + AuthType Basic + AuthName "Restricted Files" + AuthUserFile "/usr/local/apache2/auth/passwords" + AllowOverride None + Options None + Require valid-user + + # # Avoid passing HTTP_PROXY environment to CGI's on this or any proxied diff --git a/lua/dump_files.lua b/lua/dump_files.lua new file mode 100644 index 0000000..4f98bcb --- /dev/null +++ b/lua/dump_files.lua @@ -0,0 +1,42 @@ +require "apache2" + +--[[ + Dumps all the published links +--]] +function dump_files(t, r, dir) + for _, f in ipairs(r:get_direntries(dir)) do + if f ~= "." and f ~= ".." then + local filepath = dir .. "/" .. f + local info = r:stat(filepath) + if info then + -- if this is a file, then add it to the table! + if info.filetype == 1 then + t[filepath] = info + end + + -- if this is a dir, then descend into it + if info.filetype == 2 then + dump_files(t, r, filepath) + end + end + end + end +end + +function handle(r) + r.content_type = "text/plain" + + if r.method == 'GET' then + local links = {} + dump_files(links, r, r.document_root) + + for filepath, info in pairs(links) do + r:puts( ("%s\n"):format( + filepath:gsub(r.document_root, r.server_name .. ":" ..r.port) + )) + end + else + return 501 + end + return apache2.OK +end diff --git a/lua/publish.lua b/lua/publish.lua new file mode 100644 index 0000000..5fa18c0 --- /dev/null +++ b/lua/publish.lua @@ -0,0 +1,38 @@ +require "apache2" + +function publish(dir, pattern) + local cmd = ("%s/publish.sh %s"):format(dir, pattern) + local handle = io.popen(cmd) + local output = handle:read('*a') + handle:close() + + return output +end + +function get_form(dir) + local handle = io.open(dir .. '/submit.html') + local output = handle:read('*a') + handle:close() + + return output; +end + +function handle(r) + r.content_type = "text/html" + + local args = r:parseargs() + local pattern = args.pattern + + if pattern then + local nonce = publish(r.context_document_root, pattern) + local uri = ("%s://%s:%s/%s"):format( + r.is_https and "https" or "http", + r.server_name, r.port, nonce) + r:puts( ([[%s]]):format(uri, uri) ) + else + local template = get_form(r.context_document_root) + r:puts( template ) + end + + return apache2.OK +end diff --git a/lua/publish.sh b/lua/publish.sh new file mode 100755 index 0000000..bf88fbd --- /dev/null +++ b/lua/publish.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +# make sure public root and link dirs are declared +[[ -z "$PUBLIC_ROOT_DIR" ]] && echo Expected PUBLIC_ROOT_DIR && exit 1 +[[ -z "$PUBLIC_LINK_DIR" ]] && echo Expected PUBLIC_LINK_DIR && exit 1 + +[[ -z "$1" ]] && echo Expected pattern && exit 1 + +# if pattern matches files from storage, +# create nonce directory +# create symlinks to matching files +nonce=$(head /dev/urandom | sha1sum -b | awk '{print $1}') +symlink_dir=$PUBLIC_LINK_DIR/$nonce + +find $PUBLIC_ROOT_DIR -type f -name "*$1*" | while read fname +do + [[ -d $symlink_dir ]] || mkdir -p $symlink_dir + ln -s $fname $symlink_dir/$(echo $fname | sed 's|^.*/||') +done + +# print nonce directory +echo $nonce diff --git a/lua/submit.html b/lua/submit.html new file mode 100644 index 0000000..18314c9 --- /dev/null +++ b/lua/submit.html @@ -0,0 +1,24 @@ + + +Public + + + +
+ +

+

What do you want me to publish?

+ +

+ +

+ +

+ +
+ + diff --git a/public b/public deleted file mode 100755 index 2dd2481..0000000 --- a/public +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/perl -use strict; -use warnings; - -use File::Spec; -use File::Path qw/ make_path /; - -my $root_dir = $ENV{PUBLIC_ROOT_DIR} - or die "Need PUBLIC_ROOT_DIR\n"; -my $link_dir = $ENV{PUBLIC_LINK_DIR} - or die "Need PUBLIC_LINK_DIR\n"; -my $http_uri = $ENV{PUBLIC_HTTP_URI} - or die "Need PUBLIC_HTTP_URI\n"; - - -sub nonce { - my $n = shift; - $n = 10 unless $n > 0; - - my @chars = ( 'a' .. 'z', 'A' .. 'Z', '0' .. '9' ); - my @path = (); - push @path, $chars[ rand @chars ] for 1 .. $n; - - return join '', @path; -} - -sub makeNonceDir { - my $nonce = shift; - my $path = File::Spec->catdir($link_dir, $nonce); - make_path($path, { chmod => 0777 }); - return $path, ; -} - -sub addFiles { - # get list of files matching name from root directory - my $name = shift - or die "Need filename!\n"; - - opendir DIR, $root_dir - or die $!; - my @files = grep /$name/i, readdir(DIR); - closedir DIR; - - # exit if no files found - die "No match: $name\n" unless @files; - - # create nonce dir and add symbolic links - my $nonce = nonce(20); - my $nonce_dir = makeNonceDir($nonce); - - for my $file (@files) { - my $root_filepath = File::Spec->catfile($root_dir, $file); - my $link_filepath = File::Spec->catfile($nonce_dir, $file); - - symlink $root_filepath, $link_filepath - or die "Unable to create symlink: $root_filepath -> $link_filepath"; - - my $uri_link = join '/', $http_uri, $nonce, $file; - print "$uri_link\n"; - } -} - -sub listFiles { - opendir DIR, $link_dir; - my @nonces = readdir(DIR); - closedir DIR; - - for my $nonce (@nonces) { - next if $nonce eq '.'; - next if $nonce eq '..'; - - # ensure it's a directory - my $nonce_dir = File::Spec->catdir($link_dir, $nonce); - next unless -d $nonce_dir; - - # make URIs for all the files in the nonce dirs - opendir DIR, $nonce_dir; - my @files = readdir(DIR); - closedir DIR; - - for my $file (@files) { - next if $file eq '.'; - next if $file eq '..'; - - my $uri_link = join '/', $http_uri, $nonce, $file; - print "$uri_link\n"; - } - } -} - - -# script begins -if (@ARGV) { - addFiles($_) for @ARGV; -} -else { - listFiles; -} diff --git a/public.sh b/public.sh deleted file mode 100755 index 6ed9695..0000000 --- a/public.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -service=proxy_public - -for f in $(docker service ps -q $service) -do - [[ running == $(docker inspect --format '{{.Status.State}}' $f) ]] || continue - container_id=$(docker inspect --format '{{.Status.ContainerStatus.ContainerID}}' $f) - echo docker exec $container_id /root/public "$@" - docker exec $container_id /root/public "$@" -done diff --git a/readme.md b/readme.md index 27b668b..f8fb6dc 100644 --- a/readme.md +++ b/readme.md @@ -7,22 +7,12 @@ A stupid and easy way to publicize my stuff. like dropbox but safer. docker stack deploy -c <(docker-compose config) public ``` -### creating a public directory by filename regex -``` -cliftonpalmer@pop-os:~/swarm/share-public$ ./public.sh simplify -http://public.purplebirdman.online/1ojxVHOXk9u89u234erso7df/SimplifyPikoPseftis3.jpg -http://public.purplebirdman.online/1ojxVHOXk9u89u234erso7df/SimplifyPikoPseftis.png -http://public.purplebirdman.online/1ojxVHOXk9u89u234erso7df/SimplifyPikoPseftis.clip -http://public.purplebirdman.online/1ojxVHOXk9u89u234erso7df/SimplifyPikoPseftis2.png -``` +### reaching the services + +Must authorize self through ```$hostname```/lua/publish.lua and set up valid users on first deployment -### listing public directories and contents ``` -cliftonpalmer@pop-os:~/swarm/share-public$ ./public.sh -http://public.purplebirdman.online/1ojxVHOXk9u89u234erso7df/SimplifyPikoPseftis3.jpg -http://public.purplebirdman.online/1ojxVHOXk9u89u234erso7df/SimplifyPikoPseftis2.png -http://public.purplebirdman.online/1ojxVHOXk9u89u234erso7df/SimplifyPikoPseftis.png -http://public.purplebirdman.online/1ojxVHOXk9u89u234erso7df/SimplifyPikoPseftis.clip +htpasswd -c passwords $username ``` ## todo -- 2.47.2