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

public export share folder #84

Closed
mrpops2ko opened this issue May 31, 2024 · 21 comments
Closed

public export share folder #84

mrpops2ko opened this issue May 31, 2024 · 21 comments
Assignees
Labels
enhancement New feature or request

Comments

@mrpops2ko
Copy link

The way I use copyparty is situating it behind authentik, so i don't have to do any of the worrying about authentication, and let authentik do that. (alongside a reverse proxy + cloudflare) i'm sure this is common for most people.

It would be nice if we could easily create a one time use or time gated online share, located at a different address (maybe even password protected / prompted) and my friends could then share things with their friends on a one time basis.

the way i image this would work, is that each folder or file has a share button. upon clicking that you are presented with a prompt to place; 1. a password, 2. the length of the share existence, (x minutes, hours, days, weeks, months) 3. one time use download checkbox. all of these would be optional settings.

upon clicking share, a new random string (maybe something like 12 digital alpha numeric) will be created at https://copyparty.example.com/share/{random_string}

this would then allow us to create specific public whitelists for the /share/* on our reverse proxies so that they don't go through the authentication process. it doesn't specifically have to be /share/ it can be user defined or hard coded - just something that is consistent so that we can bypass authentication apps

this could also further be customised with server settings that prevent say the base directories from being shared, or putting an arbitary limit on the total size that can be shared but those two seem niche and more effort - its likely that if the person who is sharing these things with their friends, they can trust their friends not to then not share everything to the world

Describe any alternatives you've considered
i've considered using various other apps to do this instead, but its way more a hassle since it would require replicating the files, instead a copyparty native solution is the ideal medium

@mrpops2ko mrpops2ko added the enhancement New feature or request label May 31, 2024
@9001
Copy link
Owner

9001 commented May 31, 2024

I've seen this approach used in some similar servers, and it's not a bad idea -- but at the same time, copyparty already has the dirkeys/filekeys features, which are somewhat similar to this... I'm just not sure how well it'd work with authentik.

Is it possible to configure authentik to allow access to copyparty even though the user doesn't have a valid auth? As in, authentik would authenticate all users that it knows about, but in the event that someone doesn't have a valid auth, it'll still let people through, but then without including any auth headers to indicate that the user was authed?

This would allow us to use the existing dirkeys/filekeys options, and it would be safe as long as your copyparty volumes are configured to only allow access from users/groups that it knows about, so any unauthorized users would still get rejected and sent to the "login" page. However, if you then also enable dirkeys, and an unauthed user were to provide the right dirkey in the url (?k=... suffix), then they'd be allowed to access the folder. This would also work for individual files if you enable filekeys as well.

...but that said, there are some strong advantages to your suggested solution, since it's far more flexible -- the control panel could show a list of your shares and allow you to revoke them at any time, and it would be possible to share a folder with a subset of your own permissions (read-only, write-only, ...). Meanwhile, dirkeys/filekeys are entirely static, so they'd be tricky to revoke if they were to go astray, and they only allow read-access. So it's tempting to give it a shot :>

@mrpops2ko
Copy link
Author

I'm not sure it is possible to do as you've suggested with authentik, thats why just bypassing authentik entirely is usually the best play

you could possibly create a dummy user like guest/guest but then thats an always authenticated user so kind of defeats the purpose

i need to look more into the structure of the dirkeys / filekeys, because its possible that might work with some regex if its repeatable. traefik is pretty powerful on matching criteria, for example these are my bin (selfhosted pastebin) traefik rules which i use to lock everything except the viewing of pastes behind an auth screen

      - "traefik.http.routers.pastebin-public.rule=Host(`bin.example.com`) && (PathPrefix(`/p/`) || PathPrefix(`/static/`))" 
      - 'traefik.http.routers.pastebin-public.rule=Host(`bin.example.com`) && PathRegexp(`/[\w.-]+\.\w+$`)'
      - "traefik.http.routers.pastebin-public.entrypoints=websecure"
      - "traefik.http.routers.pastebin-public.service=pastebin-public"
      - "traefik.http.services.pastebin-public.loadbalancer.server.port=6163"

      - "traefik.http.routers.pastebin-private.rule=Host(`bin.example.com`)"   
      - "traefik.http.routers.pastebin-private.entrypoints=websecure"
      - "traefik.http.routers.pastebin-private.service=pastebin-private"
      - "traefik.http.services.pastebin-private.loadbalancer.server.port=6163"
      - "traefik.http.routers.pastebin-private.middlewares=authentik@file"

its possible something like this could also be done, i will go and read more documentation on how dirkeys / filekeys work, but it seems a little sparse from my reading so far (are these g / dk / y flags declared in the config file?)

@9001
Copy link
Owner

9001 commented May 31, 2024

Right, hmm... I guess this won't work then, because as soon as you enable dirkeys, all URLs are transformed to contain the correct dirkey (for sharing purposes), so even privileged users would be using the dirkey URLs to navigate around on the server. So if the presence of a dirkey is enough to get you routed past authentik, then you wouldn't be getting your intended privieges as admin.

So that kinda settles it I guess 😁

I'm not sure when I'll get a chance to work on this, but it's on the list!

@9001 9001 closed this as completed in 7c2beba Aug 18, 2024
@9001
Copy link
Owner

9001 commented Aug 19, 2024

Hey, it took a while but it's out now: https://github.com/9001/copyparty#shares

I made some conservative choices which i hope aren't too limiting:

  • if you have volumes /media and /media/music, and someone shares /media, then the music subfolder will not be visible (mainly due to a fear of unanticipated side-effects if done otherwise)
  • I didn't add the option to delete the share after the first access, since "first access" is kinda hard to formalize, and/or would decrease performance due to the necessary user tracking to pull it off well

However, the following should be all good:

  • password protection; compatible with the usual ?pw=foo url suffix and/or PW: header
  • user can choose to permit uploads into the share
  • possible to share folders or individual files, (currently) not possible to share a selection of files
  • expiration after a given time (requires some/any volume to have the database enabled using e2d)

let me know if you hit any issues 👍

@mrpops2ko
Copy link
Author

mrpops2ko commented Aug 19, 2024

Hey, it took a while but it's out now: https://github.com/9001/copyparty#shares

I made some conservative choices which i hope aren't too limiting:

  • if you have volumes /media and /media/music, and someone shares /media, then the music subfolder will not be visible (mainly due to a fear of unanticipated side-effects if done otherwise)
  • I didn't add the option to delete the share after the first access, since "first access" is kinda hard to formalize, and/or would decrease performance due to the necessary user tracking to pull it off well

However, the following should be all good:

  • password protection; compatible with the usual ?pw=foo url suffix and/or PW: header
  • user can choose to permit uploads into the share
  • possible to share folders or individual files, (currently) not possible to share a selection of files
  • expiration after a given time (requires some/any volume to have the database enabled using e2d)

let me know if you hit any issues 👍

i'm struggling to get the syntax of this down

i've tried placing

shr in the config.conf and got an error saying the format wasn't correct

i read the documentation you linked which said shr /share/ would do it but i get back this response copyparty: error: unrecognized arguments: --shr /share/

since the help info said shr [url]

i tried various iterations of shr example.com shr example.com/share/ and shr https://example.com/share/

which then all came back with errors similar to copyparty: error: unrecognized arguments: --shr https=//example.com/share/ it changed : into = even though i didn't place that in the config

any ideas what im doing wrong?

edit: figured it, it was shr=/share/

@mrpops2ko
Copy link
Author

so im still not seeing the option to share anything, do i need to be logged in / using the user login features?

idp_copyparty  | 11:09:47.417 root                  created new shares-db
idp_copyparty  | 11:09:47.418 auth                  discovered config files in /cfg => ['config.conf']
idp_copyparty  | 11:09:47.418 auth                  loaded 2 config files:
idp_copyparty  | └/z/initcfg
idp_copyparty  |  └/cfg/config.conf
idp_copyparty  | 11:09:47.419 auth                  volumes and permissions:
idp_copyparty  | 
idp_copyparty  | "/"  /w
idp_copyparty  | |    read:  everybody
idp_copyparty  | |   write:  everybody
idp_copyparty  | |    move:  --none--
idp_copyparty  | |  delete:  --none--
idp_copyparty  | |    dots:  --none--
idp_copyparty  | |     get:  --none--
idp_copyparty  | |   upGet:  --none--
idp_copyparty  | |    html:  --none--
idp_copyparty  | |  uadmin:  --none--
idp_copyparty  | 
idp_copyparty  | "/share"  
idp_copyparty  | |    read:  --none--
idp_copyparty  | |   write:  --none--
idp_copyparty  | |    move:  --none--
idp_copyparty  | |  delete:  --none--
idp_copyparty  | |    dots:  --none--
idp_copyparty  | |     get:  --none--
idp_copyparty  | |   upGet:  --none--
idp_copyparty  | |    html:  --none--
idp_copyparty  | |  uadmin:  --none--
idp_copyparty  | 
idp_copyparty  | 11:09:47.419 auth                  anyone can write to the current directory: /w
idp_copyparty  | 
idp_copyparty  | 11:09:47.419 root                  max clients: 1024
idp_copyparty  | 11:09:47.426 tcpsrv                available @  http://[::1]:3939/  (0-local only)
idp_copyparty  | 11:09:47.426 tcpsrv                available @  http://[::1]:8086/  (0-local only)
idp_copyparty  | 11:09:47.426 tcpsrv                available @  http://127.0.0.1:3939/  (1-lo)
idp_copyparty  | 11:09:47.426 tcpsrv                available @  http://127.0.0.1:8086/  (1-lo)
idp_copyparty  | 11:09:47.426 tcpsrv                available @  http://172.18.0.3:3939/  (423-eth0, external)
idp_copyparty  | 11:09:47.426 tcpsrv                available @  http://172.18.0.3:8086/  (423-eth0, external)
idp_copyparty  | 11:09:47.427 dependencies          OK: sqlite, pillow, pillow-webp, ffmpeg, ffprobe, argon2, NG: vips, mutagen, pillow-heif, pillow-avif, see --deps
idp_copyparty  | 11:09:47.427 thumb                 decoder preference: pil, ff
idp_copyparty  | 11:09:47.511 tcpsrv                listening @ [::]:8086  f5 p1
idp_copyparty  | 11:09:47.511 hsrv                  subscribed @ [::]:8086  f5 p1
idp_copyparty  | 11:09:47.511 root                  workers OK
idp_copyparty  | 
idp_copyparty  | 11:09:47.511 tcpsrv                listening @ [::]:3939  f7 p1
idp_copyparty  | 11:09:47.511 hsrv                  subscribed @ [::]:3939  f7 p1
idp_copyparty  | 11:09:47.512 up2k                  / all-default
idp_copyparty  | 11:09:47.513 cert                  using default TLS certificate; https will be insecure: /cfg/copyparty/cert.pem
11:09:47.698 up2k                    /db/o/up2k.db |1234482|
idp_copyparty  | 11:09:47.698 mtag                  could not load Mutagen, trying FFprobe instead
idp_copyparty  | 11:09:47.698 up2k                  uploads temporarily blocked due to indexing

@9001
Copy link
Owner

9001 commented Aug 19, 2024

yup! the share feature is disabled for anonymous users, since that implies you already have read-access without authentication. I assumed this would also be the case for IdP scenarios, since the IdP would provide the username in a http header.

if this doesn't fit your usecase, I can add an overload to allow creation of shares for guests as well.

@mrpops2ko
Copy link
Author

yup! the share feature is disabled for anonymous users, since that implies you already have read-access without authentication. I assumed this would also be the case for IdP scenarios, since the IdP would provide the username in a http header.

if this doesn't fit your usecase, I can add an overload to allow creation of shares for guests as well.

i make use of the authentik forward proxy, so it effectively is transparent for the user, since authentik sits at the very front and if they don't have a login it won't forward them to the cpp

authentik works by placing in the cookies the successful auth encrypted string

i created a user and the share menu appeared now, but i then got presented with the following error

ua0SVPzJhd3O

@9001
Copy link
Owner

9001 commented Aug 19, 2024

oh dear, that's what i get for only testing with Firefox... guess i've made a typo that Firefox doesn't mind, but chrome is more picky. I'll get that fixed tonight 👍

but I'm worried that your setup doesn't tell copyparty the username of the user; this is going to break a lot of assumptions I've made. For example, users will be able to see and cancel each other's uploads.

Could you enable logging of http headers for your copyparty instance and see if there's any sign of a username in there? you can do that with the following statement inside the [global] section of your config file:

ihead: *

or alternatively, as commandline argument --ihead=*

@mrpops2ko
Copy link
Author

oh dear, that's what i get for only testing with Firefox... guess i've made a typo that Firefox doesn't mind, but chrome is more picky. I'll get that fixed tonight 👍

but I'm worried that your setup doesn't tell copyparty the username of the user; this is going to break a lot of assumptions I've made. For example, users will be able to see and cancel each other's uploads.

Could you enable logging of http headers for your copyparty instance and see if there's any sign of a username in there? you can do that with the following statement inside the [global] section of your config file:

ihead: *

or alternatively, as commandline argument --ihead=*

idp_copyparty  | 12:51:46.762 172.18.0.15 46954     got header "x-forwarded-for" from untrusted source "172.18.0.15" claiming the true client ip is "192.168.1.9" (raw value: "192.168.1.9");  if you trust this, you must allowlist this proxy with "--xff-src=172.18.0.0/16" or "--xff-src=lan"  Note: depending on your reverse-proxy, and/or WAF, and/or other intermediates, you may want to read the true client IP from another header by also specifying "--xff-hdr=SomeOtherHeader"
idp_copyparty  | 12:51:46.762 172.18.0.15 46954     [H] accept: [text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7]
idp_copyparty  | 12:51:46.762 172.18.0.15 46954     [H] accept-encoding: [gzip, deflate, br, zstd]
idp_copyparty  | 12:51:46.762 172.18.0.15 46954     [H] accept-language: [en-GB,en;q=0.9]
idp_copyparty  | 12:51:46.763 172.18.0.15 46954     [H] cookie: [js=y; authentik_proxy_****=******; cppws= mrpops2ko ]
idp_copyparty  | 12:51:46.763 172.18.0.15 46954     [H] host: [files.example.com]
idp_copyparty  | 12:51:46.763 172.18.0.15 46954     [H] priority: [u=0, i]
idp_copyparty  | 12:51:46.763 172.18.0.15 46954     [H] sec-ch-ua: ["Not)A;Brand";v="99", "Google Chrome";v="127", "Chromium";v="127"]
idp_copyparty  | 12:51:46.763 172.18.0.15 46954     [H] sec-ch-ua-mobile: [?0]
idp_copyparty  | 12:51:46.763 172.18.0.15 46954     [H] sec-ch-ua-platform: ["Windows"]
idp_copyparty  | 12:51:46.763 172.18.0.15 46954     [H] sec-fetch-dest: [document]
idp_copyparty  | 12:51:46.763 172.18.0.15 46954     [H] sec-fetch-mode: [navigate]
idp_copyparty  | 12:51:46.763 172.18.0.15 46954     [H] sec-fetch-site: [none]
idp_copyparty  | 12:51:46.763 172.18.0.15 46954     [H] sec-fetch-user: [?1]
idp_copyparty  | 12:51:46.763 172.18.0.15 46954     [H] upgrade-insecure-requests: [1]
idp_copyparty  | 12:51:46.763 172.18.0.15 46954     [H] user-agent: [Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36]
idp_copyparty  | 12:51:46.763 172.18.0.15 46954     [H] x-authentik-email: [*@*.com]
idp_copyparty  | 12:51:46.763 172.18.0.15 46954     [H] x-authentik-groups: [authentik *|*|*|*]
idp_copyparty  | 12:51:46.763 172.18.0.15 46954     [H] x-authentik-jwt: [*.*.*_*_*]
idp_copyparty  | 12:51:46.763 172.18.0.15 46954     [H] x-authentik-meta-app: [files]
idp_copyparty  | 12:51:46.763 172.18.0.15 46954     [H] x-authentik-meta-jwks: [https://auth.example.com/application/o/files/jwks/]
idp_copyparty  | 12:51:46.763 172.18.0.15 46954     [H] x-authentik-meta-outpost: [authentik Embedded Outpost]
idp_copyparty  | 12:51:46.763 172.18.0.15 46954     [H] x-authentik-meta-provider: [Provider for Files]
idp_copyparty  | 12:51:46.763 172.18.0.15 46954     [H] x-authentik-meta-version: [goauthentik.io/outpost/2024.6.3]
idp_copyparty  | 12:51:46.763 172.18.0.15 46954     [H] x-authentik-name: [*]
idp_copyparty  | 12:51:46.763 172.18.0.15 46954     [H] x-authentik-uid: [*]
idp_copyparty  | 12:51:46.763 172.18.0.15 46954     [H] x-authentik-username: [*]
idp_copyparty  | 12:51:46.763 172.18.0.15 46954     [H] x-forwarded-for: [192.168.1.9]
idp_copyparty  | 12:51:46.763 172.18.0.15 46954     [H] x-forwarded-host: [files.example.com]
idp_copyparty  | 12:51:46.763 172.18.0.15 46954     [H] x-forwarded-port: [443]
idp_copyparty  | 12:51:46.763 172.18.0.15 46954     [H] x-forwarded-proto: [https]
idp_copyparty  | 12:51:46.763 172.18.0.15 46954     [H] x-forwarded-server: [*]
idp_copyparty  | 12:51:46.763 172.18.0.15 46954     [H] x-real-ip: [192.168.1.9]
idp_copyparty  | 12:51:46.763 172.18.0.15 46954     GET  / @mrpops2ko
idp_copyparty  | 12:51:46.774 u2idx                 opened /db/o/up2k.db
idp_copyparty  | 12:51:46.806 172.18.0.15 46954     got header "x-forwarded-for" from untrusted source "172.18.0.15" claiming the true client ip is "192.168.1.9" (raw value: "192.168.1.9");  if you trust this, you must allowlist this proxy with "--xff-src=172.18.0.0/16" or "--xff-src=lan"  Note: depending on your reverse-proxy, and/or WAF, and/or other intermediates, you may want to read the true client IP from another header by also specifying "--xff-hdr=SomeOtherHeader"
idp_copyparty  | 12:51:46.808 172.18.0.15 46956     got header "x-forwarded-for" from untrusted source "172.18.0.15" claiming the true client ip is "192.168.1.9" (raw value: "192.168.1.9");  if you trust this, you must allowlist this proxy with "--xff-src=172.18.0.0/16" or "--xff-src=lan"  Note: depending on your reverse-proxy, and/or WAF, and/or other intermediates, you may want to read the true client IP from another header by also specifying "--xff-hdr=SomeOtherHeader"
idp_copyparty  | 12:51:46.811 172.18.0.15 46956     got header "x-forwarded-for" from untrusted source "172.18.0.15" claiming the true client ip is "192.168.1.9" (raw value: "192.168.1.9");  if you trust this, you must allowlist this proxy with "--xff-src=172.18.0.0/16" or "--xff-src=lan"  Note: depending on your reverse-proxy, and/or WAF, and/or other intermediates, you may want to read the true client IP from another header by also specifying "--xff-hdr=SomeOtherHeader"
idp_copyparty  | 12:51:46.811 172.18.0.15 46954     got header "x-forwarded-for" from untrusted source "172.18.0.15" claiming the true client ip is "192.168.1.9" (raw value: "192.168.1.9");  if you trust this, you must allowlist this proxy with "--xff-src=172.18.0.0/16" or "--xff-src=lan"  Note: depending on your reverse-proxy, and/or WAF, and/or other intermediates, you may want to read the true client IP from another header by also specifying "--xff-hdr=SomeOtherHeader"
idp_copyparty  | 12:51:46.812 172.18.0.15 46958     got header "x-forwarded-for" from untrusted source "172.18.0.15" claiming the true client ip is "192.168.1.9" (raw value: "192.168.1.9");  if you trust this, you must allowlist this proxy with "--xff-src=172.18.0.0/16" or "--xff-src=lan"  Note: depending on your reverse-proxy, and/or WAF, and/or other intermediates, you may want to read the true client IP from another header by also specifying "--xff-hdr=SomeOtherHeader"
idp_copyparty  | 12:51:46.813 172.18.0.15 46956     got header "x-forwarded-for" from untrusted source "172.18.0.15" claiming the true client ip is "192.168.1.9" (raw value: "192.168.1.9");  if you trust this, you must allowlist this proxy with "--xff-src=172.18.0.0/16" or "--xff-src=lan"  Note: depending on your reverse-proxy, and/or WAF, and/or other intermediates, you may want to read the true client IP from another header by also specifying "--xff-hdr=SomeOtherHeader"
idp_copyparty  | 12:51:46.848 172.18.0.15 46956     got header "x-forwarded-for" from untrusted source "172.18.0.15" claiming the true client ip is "192.168.1.9" (raw value: "192.168.1.9");  if you trust this, you must allowlist this proxy with "--xff-src=172.18.0.0/16" or "--xff-src=lan"  Note: depending on your reverse-proxy, and/or WAF, and/or other intermediates, you may want to read the true client IP from another header by also specifying "--xff-hdr=SomeOtherHeader"
idp_copyparty  | 12:51:46.855 172.18.0.15 46956     got header "x-forwarded-for" from untrusted source "172.18.0.15" claiming the true client ip is "192.168.1.9" (raw value: "192.168.1.9");  if you trust this, you must allowlist this proxy with "--xff-src=172.18.0.0/16" or "--xff-src=lan"  Note: depending on your reverse-proxy, and/or WAF, and/or other intermediates, you may want to read the true client IP from another header by also specifying "--xff-hdr=SomeOtherHeader"
idp_copyparty  | 12:51:46.855 172.18.0.15 46956     [H] accept: [*/*]
idp_copyparty  | 12:51:46.855 172.18.0.15 46956     [H] accept-encoding: [gzip, deflate, br, zstd]
idp_copyparty  | 12:51:46.855 172.18.0.15 46956     [H] accept-language: [en-GB,en;q=0.9]
idp_copyparty  | 12:51:46.855 172.18.0.15 46956     [H] cookie: [js=y; authentik_proxy_*=*; cppws= mrpops2ko ]
idp_copyparty  | 12:51:46.855 172.18.0.15 46956     [H] host: [files.example.com]
idp_copyparty  | 12:51:46.855 172.18.0.15 46956     [H] priority: [u=1, i]
idp_copyparty  | 12:51:46.855 172.18.0.15 46956     [H] referer: [https://files.example.com/]
idp_copyparty  | 12:51:46.855 172.18.0.15 46956     [H] sec-ch-ua: ["Not)A;Brand";v="99", "Google Chrome";v="127", "Chromium";v="127"]
idp_copyparty  | 12:51:46.855 172.18.0.15 46956     [H] sec-ch-ua-mobile: [?0]
idp_copyparty  | 12:51:46.855 172.18.0.15 46956     [H] sec-ch-ua-platform: ["Windows"]
idp_copyparty  | 12:51:46.855 172.18.0.15 46956     [H] sec-fetch-dest: [empty]
idp_copyparty  | 12:51:46.855 172.18.0.15 46956     [H] sec-fetch-mode: [cors]
idp_copyparty  | 12:51:46.855 172.18.0.15 46956     [H] sec-fetch-site: [same-origin]
idp_copyparty  | 12:51:46.855 172.18.0.15 46956     [H] user-agent: [Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36]
idp_copyparty  | 12:51:46.855 172.18.0.15 46956     [H] x-authentik-email: [*@*.com]
idp_copyparty  | 12:51:46.855 172.18.0.15 46956     [H] x-authentik-groups: [* *|*|*|*]
idp_copyparty  | 12:51:46.855 172.18.0.15 46956     [H] x-authentik-jwt: [*.*.*_*_*]
idp_copyparty  | 12:51:46.855 172.18.0.15 46956     [H] x-authentik-meta-app: [files]
idp_copyparty  | 12:51:46.855 172.18.0.15 46956     [H] x-authentik-meta-jwks: [https://auth.example.com/application/o/files/jwks/]
idp_copyparty  | 12:51:46.855 172.18.0.15 46956     [H] x-authentik-meta-outpost: [authentik Embedded Outpost]
idp_copyparty  | 12:51:46.855 172.18.0.15 46956     [H] x-authentik-meta-provider: [Provider for Files]
idp_copyparty  | 12:51:46.855 172.18.0.15 46956     [H] x-authentik-meta-version: [goauthentik.io/outpost/2024.6.3]
idp_copyparty  | 12:51:46.856 172.18.0.15 46956     [H] x-authentik-name: [*]
idp_copyparty  | 12:51:46.856 172.18.0.15 46956     [H] x-authentik-uid: [*]
idp_copyparty  | 12:51:46.856 172.18.0.15 46956     [H] x-authentik-username: [*]
idp_copyparty  | 12:51:46.856 172.18.0.15 46956     [H] x-forwarded-for: [192.168.1.9]
idp_copyparty  | 12:51:46.856 172.18.0.15 46956     [H] x-forwarded-host: [files.example.com]
idp_copyparty  | 12:51:46.856 172.18.0.15 46956     [H] x-forwarded-port: [443]
idp_copyparty  | 12:51:46.856 172.18.0.15 46956     [H] x-forwarded-proto: [https]
idp_copyparty  | 12:51:46.856 172.18.0.15 46956     [H] x-forwarded-server: [*]
idp_copyparty  | 12:51:46.856 172.18.0.15 46956     [H] x-real-ip: [192.168.1.9]
idp_copyparty  | 12:51:46.856 172.18.0.15 46956     GET  /?tree= @mrpops2ko

i obfuscated the logs a bit to remove important info but if you need some better examples with populated dummy data i can provide them, this was with me logged into cpp

when logged out, i can only see the authentik related username stuff but i'm not sure if the application itself is aware of that, the headers that are used are

                authResponseHeaders:
                    - X-authentik-username
                    - X-authentik-groups
                    - X-authentik-email
                    - X-authentik-name
                    - X-authentik-uid
                    - X-authentik-jwt
                    - X-authentik-meta-jwks
                    - X-authentik-meta-outpost
                    - X-authentik-meta-provider
                    - X-authentik-meta-app
                    - X-authentik-meta-version

this is the forward auth documentation for authentik

i've tested it out on firefox and the implementation works great

as a minor QOL idea, could you pre-populate the share name with a random string as if the random button was pressed? it shouldn't be too much of a hassle for the user to delete it, and it would save them having to click the button each time (or maybe some kind of random always flag in config)

i'll try create a share now and access it unauthed

@9001
Copy link
Owner

9001 commented Aug 19, 2024

could you pre-populate the share name with a random string as if the random button was pressed?

oh that's something i forgot to document -- if you click "create share" without any text in the name field, it does exactly that :> the reason was to keep the name-field empty, so it's easier to fill in a custom value if you wanna do that. Should mention that in the tooltip for the name-field, unless you have any better ideas?

[H] x-authentik-username: [*]

I think this is what we're looking for -- if you provide this header-name instead of the example x-idp-user value in the example idp config then copyparty should be able to connect the dots.

but there's some more things we should look at,

got header "x-forwarded-for" from untrusted source "172.18.0.15" claiming the true client ip is "192.168.1.9" (raw value: "192.168.1.9"); if you trust this, you must allowlist this proxy with "--xff-src=172.18.0.0/16" or "--xff-src=lan" Note: depending on your reverse-proxy, and/or WAF, and/or other intermediates, you may want to read the true client IP from another header by also specifying "--xff-hdr=SomeOtherHeader"
[H] x-forwarded-for: [192.168.1.9]

your reverse-proxy is telling copyparty that your IP (the IP you sent the request from) is 192.168.1.9, but copyparty doesn't trust that hint, because the xff-src config value is too restrictive. The suggested fix of setting xff-src: lan in the [global] section is probably safe,.

However there's one more thing I'm wondering -- is it true that the IP you sent the request from is actually 192.168.1.9 , meaning you're on the same LAN as the server, and not accessing it through a domain?

the reason I'm asking is because copyparty needs to know the correct IP and username of each user to function correctly.

@mrpops2ko
Copy link
Author

ah ok if it generates a random string then its all good

one thing that i have encountered, is that when i first made my first share i got a nice popup offering me the link

unfortuantely for any subsequent share creation, that menu isn't coming up anymore

also theres another issue, which im guessing shouldn't be too dififcult to solve i just need to find the elements that need to be loaded, but this is how the menus look when i access the public shares now lol

WSBXf3LP0mlJ

this is of course because the elements themselves are locked behind an authentik login screen and an external user doesn't have authentication for them

are all the UI related js locked behind /.cpr/? for example i see /.cpr/browser.css?_=w04D

i'm trying to whittle it down to the concept of least privilege
pGKCnEcw4t1S
are all these essential to load the UI or can i remove some of them?

    labels:
    - "traefik.enable=true"
    #public
    - "traefik.http.routers.fs-public.rule=Host(`files.example..com`) && PathPrefix(`/share/`) && PathRegexp(`.+`)"
    - "traefik.http.routers.fs-public.entrypoints=websecure"
    - "traefik.http.routers.fs-public.service=fs-public-service"
    - "traefik.http.services.fs-public-service.loadbalancer.server.port=8086"
    #private
    - "traefik.http.routers.fs-private.rule=Host(`files.example.com`)"
    - "traefik.http.routers.fs-private.entrypoints=websecure"
    - "traefik.http.routers.fs-private.service=fs-private-service"
    - "traefik.http.routers.fs-private.middlewares=authentik@file"
    - "traefik.http.services.fs-private-service.loadbalancer.server.port=8086"

@mrpops2ko
Copy link
Author

hmm i added

  idp-h-usr: x-authentik-username
  idp-h-grp: x-authentik-groups

to the config.conf file

my entire file being
eRMLMygv5ard

now im getting this error

idp_copyparty  | Traceback (most recent call last):
idp_copyparty  |   File "<frozen runpy>", line 198, in _run_module_as_main
idp_copyparty  |   File "<frozen runpy>", line 88, in _run_code
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/__main__.py", line 1738, in <module>
idp_copyparty  |     main()
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/__main__.py", line 1734, in main
idp_copyparty  |     SvcHub(al, dal, argv, "".join(printed)).run()
idp_copyparty  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/svchub.py", line 223, in __init__
idp_copyparty  |     self.asrv = AuthSrv(self.args, self.log, dargs=self.dargs)
idp_copyparty  |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/authsrv.py", line 813, in __init__
idp_copyparty  |     self.reload()
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/authsrv.py", line 1340, in reload
idp_copyparty  |     self._reload(verbosity)
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/authsrv.py", line 1471, in _reload
idp_copyparty  |     par = vfs.all_vols[""]
idp_copyparty  |           ~~~~~~~~~~~~^^^^
idp_copyparty  | KeyError: ''
idp_copyparty  | copyparty v1.14.1 "one step forward" (2024-08-19)
idp_copyparty  |   CPython v3.12.3 on Linux64  [GCC 13.2.1 20240309]
idp_copyparty  |    sqlite 3.45.3*1 | jinja 3.1.4 | pyftpd 1.5.10 | tftp 0.4.0
idp_copyparty  | 
idp_copyparty  | 2024-08-19
idp_copyparty  | 14:40:15.637 root                  initializing shares-db /cfg/copyparty/shares.db
idp_copyparty  | 14:40:15.637 auth                  discovered config files in /cfg => ['config.conf']
idp_copyparty  | 14:40:15.637 auth                  loaded 2 config files:
idp_copyparty  | └/z/initcfg
idp_copyparty  |  └/cfg/config.conf
idp_copyparty  | Traceback (most recent call last):
idp_copyparty  |   File "<frozen runpy>", line 198, in _run_module_as_main
idp_copyparty  |   File "<frozen runpy>", line 88, in _run_code
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/__main__.py", line 1738, in <module>
idp_copyparty  |     main()
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/__main__.py", line 1734, in main
idp_copyparty  |     SvcHub(al, dal, argv, "".join(printed)).run()
idp_copyparty  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/svchub.py", line 223, in __init__
idp_copyparty  |     self.asrv = AuthSrv(self.args, self.log, dargs=self.dargs)
idp_copyparty  |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/authsrv.py", line 813, in __init__
idp_copyparty  |     self.reload()
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/authsrv.py", line 1340, in reload
idp_copyparty  |     self._reload(verbosity)
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/authsrv.py", line 1471, in _reload
idp_copyparty  |     par = vfs.all_vols[""]
idp_copyparty  |           ~~~~~~~~~~~~^^^^
idp_copyparty  | KeyError: ''
idp_copyparty  | copyparty v1.14.1 "one step forward" (2024-08-19)
idp_copyparty  |   CPython v3.12.3 on Linux64  [GCC 13.2.1 20240309]
idp_copyparty  |    sqlite 3.45.3*1 | jinja 3.1.4 | pyftpd 1.5.10 | tftp 0.4.0
idp_copyparty  | 
idp_copyparty  | 2024-08-19
idp_copyparty  | 14:40:18.176 root                  initializing shares-db /cfg/copyparty/shares.db
idp_copyparty  | 14:40:18.177 auth                  discovered config files in /cfg => ['config.conf']
idp_copyparty  | 14:40:18.177 auth                  loaded 2 config files:
idp_copyparty  | └/z/initcfg
idp_copyparty  |  └/cfg/config.conf
idp_copyparty  | Traceback (most recent call last):
idp_copyparty  |   File "<frozen runpy>", line 198, in _run_module_as_main
idp_copyparty  |   File "<frozen runpy>", line 88, in _run_code
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/__main__.py", line 1738, in <module>
idp_copyparty  |     main()
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/__main__.py", line 1734, in main
idp_copyparty  |     SvcHub(al, dal, argv, "".join(printed)).run()
idp_copyparty  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/svchub.py", line 223, in __init__
idp_copyparty  |     self.asrv = AuthSrv(self.args, self.log, dargs=self.dargs)
idp_copyparty  |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/authsrv.py", line 813, in __init__
idp_copyparty  |     self.reload()
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/authsrv.py", line 1340, in reload
idp_copyparty  |     self._reload(verbosity)
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/authsrv.py", line 1471, in _reload
idp_copyparty  |     par = vfs.all_vols[""]
idp_copyparty  |           ~~~~~~~~~~~~^^^^
idp_copyparty  | KeyError: ''
idp_copyparty  | copyparty v1.14.1 "one step forward" (2024-08-19)
idp_copyparty  |   CPython v3.12.3 on Linux64  [GCC 13.2.1 20240309]
idp_copyparty  |    sqlite 3.45.3*1 | jinja 3.1.4 | pyftpd 1.5.10 | tftp 0.4.0
idp_copyparty  | 
idp_copyparty  | 2024-08-19
idp_copyparty  | 14:40:19.337 root                  initializing shares-db /cfg/copyparty/shares.db
idp_copyparty  | 14:40:19.338 auth                  discovered config files in /cfg => ['config.conf']
idp_copyparty  | 14:40:19.338 auth                  loaded 2 config files:
idp_copyparty  | └/z/initcfg
idp_copyparty  |  └/cfg/config.conf
idp_copyparty  | Traceback (most recent call last):
idp_copyparty  |   File "<frozen runpy>", line 198, in _run_module_as_main
idp_copyparty  |   File "<frozen runpy>", line 88, in _run_code
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/__main__.py", line 1738, in <module>
idp_copyparty  |     main()
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/__main__.py", line 1734, in main
idp_copyparty  |     SvcHub(al, dal, argv, "".join(printed)).run()
idp_copyparty  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/svchub.py", line 223, in __init__
idp_copyparty  |     self.asrv = AuthSrv(self.args, self.log, dargs=self.dargs)
idp_copyparty  |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/authsrv.py", line 813, in __init__
idp_copyparty  |     self.reload()
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/authsrv.py", line 1340, in reload
idp_copyparty  |     self._reload(verbosity)
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/authsrv.py", line 1471, in _reload
idp_copyparty  |     par = vfs.all_vols[""]
idp_copyparty  |           ~~~~~~~~~~~~^^^^
idp_copyparty  | KeyError: ''
idp_copyparty  | copyparty v1.14.1 "one step forward" (2024-08-19)
idp_copyparty  |   CPython v3.12.3 on Linux64  [GCC 13.2.1 20240309]
idp_copyparty  |    sqlite 3.45.3*1 | jinja 3.1.4 | pyftpd 1.5.10 | tftp 0.4.0
idp_copyparty  | 
idp_copyparty  | 2024-08-19
idp_copyparty  | 14:40:20.407 root                  initializing shares-db /cfg/copyparty/shares.db
idp_copyparty  | 14:40:20.407 auth                  discovered config files in /cfg => ['config.conf']
idp_copyparty  | 14:40:20.407 auth                  loaded 2 config files:
idp_copyparty  | └/z/initcfg
idp_copyparty  |  └/cfg/config.conf
idp_copyparty  | Traceback (most recent call last):
idp_copyparty  |   File "<frozen runpy>", line 198, in _run_module_as_main
idp_copyparty  |   File "<frozen runpy>", line 88, in _run_code
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/__main__.py", line 1738, in <module>
idp_copyparty  |     main()
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/__main__.py", line 1734, in main
idp_copyparty  |     SvcHub(al, dal, argv, "".join(printed)).run()
idp_copyparty  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/svchub.py", line 223, in __init__
idp_copyparty  |     self.asrv = AuthSrv(self.args, self.log, dargs=self.dargs)
idp_copyparty  |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/authsrv.py", line 813, in __init__
idp_copyparty  |     self.reload()
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/authsrv.py", line 1340, in reload
idp_copyparty  |     self._reload(verbosity)
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/authsrv.py", line 1471, in _reload
idp_copyparty  |     par = vfs.all_vols[""]
idp_copyparty  |           ~~~~~~~~~~~~^^^^
idp_copyparty  | KeyError: ''
idp_copyparty  | copyparty v1.14.1 "one step forward" (2024-08-19)
idp_copyparty  |   CPython v3.12.3 on Linux64  [GCC 13.2.1 20240309]
idp_copyparty  |    sqlite 3.45.3*1 | jinja 3.1.4 | pyftpd 1.5.10 | tftp 0.4.0
idp_copyparty  | 
idp_copyparty  | 2024-08-19
idp_copyparty  | 14:40:21.895 root                  initializing shares-db /cfg/copyparty/shares.db
idp_copyparty  | 14:40:21.895 auth                  discovered config files in /cfg => ['config.conf']
idp_copyparty  | 14:40:21.895 auth                  loaded 2 config files:
idp_copyparty  | └/z/initcfg
idp_copyparty  |  └/cfg/config.conf
idp_copyparty  | Traceback (most recent call last):
idp_copyparty  |   File "<frozen runpy>", line 198, in _run_module_as_main
idp_copyparty  |   File "<frozen runpy>", line 88, in _run_code
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/__main__.py", line 1738, in <module>
idp_copyparty  |     main()
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/__main__.py", line 1734, in main
idp_copyparty  |     SvcHub(al, dal, argv, "".join(printed)).run()
idp_copyparty  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/svchub.py", line 223, in __init__
idp_copyparty  |     self.asrv = AuthSrv(self.args, self.log, dargs=self.dargs)
idp_copyparty  |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/authsrv.py", line 813, in __init__
idp_copyparty  |     self.reload()
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/authsrv.py", line 1340, in reload
idp_copyparty  |     self._reload(verbosity)
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/authsrv.py", line 1471, in _reload
idp_copyparty  |     par = vfs.all_vols[""]
idp_copyparty  |           ~~~~~~~~~~~~^^^^
idp_copyparty  | KeyError: ''
idp_copyparty  | copyparty v1.14.1 "one step forward" (2024-08-19)
idp_copyparty  |   CPython v3.12.3 on Linux64  [GCC 13.2.1 20240309]
idp_copyparty  |    sqlite 3.45.3*1 | jinja 3.1.4 | pyftpd 1.5.10 | tftp 0.4.0
idp_copyparty  | 
idp_copyparty  | 2024-08-19
idp_copyparty  | 14:40:24.434 root                  initializing shares-db /cfg/copyparty/shares.db
idp_copyparty  | 14:40:24.435 auth                  discovered config files in /cfg => ['config.conf']
idp_copyparty  | 14:40:24.435 auth                  loaded 2 config files:
idp_copyparty  | └/z/initcfg
idp_copyparty  |  └/cfg/config.conf
idp_copyparty  | Traceback (most recent call last):
idp_copyparty  |   File "<frozen runpy>", line 198, in _run_module_as_main
idp_copyparty  |   File "<frozen runpy>", line 88, in _run_code
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/__main__.py", line 1738, in <module>
idp_copyparty  |     main()
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/__main__.py", line 1734, in main
idp_copyparty  |     SvcHub(al, dal, argv, "".join(printed)).run()
idp_copyparty  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/svchub.py", line 223, in __init__
idp_copyparty  |     self.asrv = AuthSrv(self.args, self.log, dargs=self.dargs)
idp_copyparty  |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/authsrv.py", line 813, in __init__
idp_copyparty  |     self.reload()
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/authsrv.py", line 1340, in reload
idp_copyparty  | copyparty v1.14.1 "one step forward" (2024-08-19)
idp_copyparty  |   CPython v3.12.3 on Linux64  [GCC 13.2.1 20240309]
idp_copyparty  |    sqlite 3.45.3*1 | jinja 3.1.4 | pyftpd 1.5.10 | tftp 0.4.0
idp_copyparty  | 
idp_copyparty  | 2024-08-19
idp_copyparty  | 14:40:28.617 root                  initializing shares-db /cfg/copyparty/shares.db
idp_copyparty  | 14:40:28.618 auth                  discovered config files in /cfg => ['config.conf']
idp_copyparty  | 14:40:28.618 auth                  loaded 2 config files:
idp_copyparty  |     self._reload(verbosity)
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/authsrv.py", line 1471, in _reload
idp_copyparty  |     par = vfs.all_vols[""]
idp_copyparty  |           ~~~~~~~~~~~~^^^^
idp_copyparty  | KeyError: ''
idp_copyparty  | └/z/initcfg
idp_copyparty  |  └/cfg/config.conf
idp_copyparty  | Traceback (most recent call last):
idp_copyparty  |   File "<frozen runpy>", line 198, in _run_module_as_main
idp_copyparty  |   File "<frozen runpy>", line 88, in _run_code
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/__main__.py", line 1738, in <module>
idp_copyparty  |     main()
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/__main__.py", line 1734, in main
idp_copyparty  |     SvcHub(al, dal, argv, "".join(printed)).run()
idp_copyparty  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/svchub.py", line 223, in __init__
idp_copyparty  |     self.asrv = AuthSrv(self.args, self.log, dargs=self.dargs)
idp_copyparty  |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/authsrv.py", line 813, in __init__
idp_copyparty  |     self.reload()
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/authsrv.py", line 1340, in reload
idp_copyparty  |     self._reload(verbosity)
idp_copyparty  |   File "/usr/lib/python3.12/site-packages/copyparty/authsrv.py", line 1471, in _reload
idp_copyparty  |     par = vfs.all_vols[""]
idp_copyparty  |           ~~~~~~~~~~~~^^^^
idp_copyparty  | KeyError: ''
idp_copyparty  | copyparty v1.14.1 "one step forward" (2024-08-19)
idp_copyparty  |   CPython v3.12.3 on Linux64  [GCC 13.2.1 20240309]
idp_copyparty  |    sqlite 3.45.3*1 | jinja 3.1.4 | pyftpd 1.5.10 | tftp 0.4.0
idp_copyparty  | 
idp_copyparty  | 2024-08-19
idp_copyparty  | 14:40:39.308 root                  initializing shares-db /cfg/copyparty/shares.db
idp_copyparty  | 14:40:39.309 auth                  discovered config files in /cfg => ['config.conf']
idp_copyparty  | 14:40:39.309 auth                  loaded 2 config files:
idp_copyparty  | └/z/initcfg
idp_copyparty  |  └/cfg/config.conf

@9001
Copy link
Owner

9001 commented Aug 19, 2024

unfortuantely for any subsequent share creation, that menu isn't coming up anymore

aight, I'll take a look at that too 👌

are all the UI related js locked behind /.cpr/?

yeah, at minimum you'll want to allow all traffic to regex ^\.cpr/[a-z0-9]+\.[a-z0-9\.]+$ meaning it will allow access to all the top-level files inside the .cpr folder which have a file extension --

the reason I'm being specific about "only files with a file extension" is because the .cpr folder serves a few other purposes as well;

  • .cpr/*.* are the html, css and js files which are absolutely necessary
  • .cpr/ico/* is used to generate icons (not thumbnails) in the grid view
  • .cpr/ssdp/*.xml is used for dynamic discovery from windows file explorer, if enabled with global-option -z or -zs
  • .cpr/metrics provides Prometheus metrics, if enabled with global-option --stats and the requesting user has admin access

so it depends on your config , but with the default settings it'll be fine to just allow all access to all of .cpr as well. Note that the list above uses glob-syntax for the paths, let me know if you need help with a regex alternative if you wanna be that specific :>

par = vfs.all_vols[""]

heh, yep that sounds like a bug (luckily isolated to just this new feature) -- thx, I'll take a look tonight 👍 don't have access to the code rn

@mrpops2ko
Copy link
Author

mrpops2ko commented Aug 19, 2024

https://github.com/9001/copyparty/blob/hovudstraum/copyparty/authsrv.py#L1340
i think it might be this?

i think its replacing the dashes in

  idp-h-usr: x-authentik-username
  idp-h-grp: x-authentik-groups

edit: ignore me, stripping it out doesn't resolve it

@mrpops2ko
Copy link
Author

is it possible to remove this login prompt?

if you attempt to access a share which doesn't exist then you are presented with this
XXicahpqxK4p

but ideally it would be better if that login for more was placed behind its own login page, so i can place authentik in front of it

@9001
Copy link
Owner

9001 commented Aug 19, 2024

is it possible to remove this login prompt?

yes, but that is where you type in the password to view a password-protected share :p

the way the shares work internally is that they pretend to be volumes, so they use the regular login system if they have a password. That felt like a much better approach than reinventing a lot of access-control stuff, even if it looks a bit funky hehe

but I just realized that it's entirely possible to provide an alternative "login" screen, and show that instead when you're trying to access a share instead of a regular password-protected area, so I'll add that 👍 thx!

@mrpops2ko
Copy link
Author

this was the set of labels that seem to work for me, the hope being that it adds a bit of a stop on trying to directory traverse just in case, since you can't hit /../ without hitting an authentik login screen

    labels:
    - "traefik.enable=true"
    #public
    - "traefik.http.routers.fs-public.rule=Host(`files.example.com`) && (PathRegexp(`/share/[^/]+(/.*)?$`) || PathRegexp(`^/.cpr/[a-z0-9]+.?[a-z0-9.]*$`))"
    - "traefik.http.routers.fs-public.entrypoints=websecure"
    - "traefik.http.routers.fs-public.service=fs-public-service"
    - "traefik.http.services.fs-public-service.loadbalancer.server.port=8086"
    #private
    - "traefik.http.routers.fs-private.rule=Host(`files.example.com`)"
    - "traefik.http.routers.fs-private.entrypoints=websecure"
    # - "traefik.http.routers.fs-private.tls=true"
    - "traefik.http.routers.fs-private.service=fs-private-service"
    - "traefik.http.routers.fs-private.middlewares=authentik@file"
    - "traefik.http.services.fs-private-service.loadbalancer.server.port=8086"

another issue i noticed, is that when i created a share - it seems to display all the other directories (which i'd assume shouldn't be visible for a user visiting via a share link) if they attempt to navigate to them, authentik would deny them so it works fine but ideally those top level directories shouldn't be listed at all

b1ojNvn4EQ6s

additionally whilst the logic for the empty name field for the share being a random string makes sense when st=2, if you are trying to share a single file st=1 i think it would make more sense to default to the original filename, but mask the directory so instead of it being something like /share/a8ew666t9s4v.epub it would instead become /share/a8ew666t9s4v/original_filename.epub

a nice feature to the shares panel would be being able to either mouse over or just inline convert the unix timestamp into local timezone stuff, as well as being able to click a button to extend the time period by the original set duration (so if it was set to expire in a day, then clicking once would increment it by 1 day, clicking twice by 2 days etc)

finally the post share creation menu which allows you to copy to clipboard has returned, i've confirmed the reason why is that the up2k file indexer prevents the creation of shares during its scan period - whether this is a desired behaviour i have no clue, i'd guess not?

@9001 9001 reopened this Aug 19, 2024
@9001
Copy link
Owner

9001 commented Aug 19, 2024

when i created a share - it seems to display all the other directories (which i'd assume shouldn't be visible for a user visiting via a share link)

I'm sorry to say that this will not be a bulletproof way to prevent unintended access outside the shares; or at the very least you shouldn't expect that to be the case, even if it possibly might be right now... We're coming back to my concerns that copyparty needs to know the user's IP and username to function correctly, even if you're authenticating through an IdP. The HTTP API is designed around this assumption.

In order to prevent unintended access, you'll need to configure your volumes to only allow access for a list of trusted users, or a trusted group of users. When configured correctly, the IdP can provide all of this dynamically. I'm not an expert on this topic, but maybe we can figure this out together --

going back to the example idp config, we have this part:

[/]      # create a volume at "/" (the webroot), which will
  /w     # share /w (the docker data volume, which is mapped to /srv/pub on the host in docker-compose.yml)
  accs:
    rw: *       # everyone gets read-access, but
    rwmda: @su  # the group "su" gets read-write-move-delete-admin

that creates a volume which is read-write-access for unauthorized users, but read-write-move-delete-admin for all members of the IdP usergroup su.

if you remove the rw: * part, I think we're getting close to the behavior you're looking for :>

i think it would make more sense to default to the original filename, but mask the directory

good idea -- although it'll be a bit trickier to pull off than the current approach, it shouldn't be too bad -- I'll give it a go!

inline convert the unix timestamp into local timezone stuff

absolutely, the shares listing was thrown together in a rush so I didn't really stop to think xD

being able to click a button to extend the time period by the original set duration

interesting idea, I'll check it out.

the up2k file indexer prevents the creation of shares during its scan period

aw man, yeah you're probably right. That's a limitation of the current design -- this one runs deep and might be real tricky to do anything about... sorry heh

I'm still not quite home so haven't started looking at any of the issues, might at least get a beta up tonight to fix the biggest issues, let's see :>

@9001
Copy link
Owner

9001 commented Aug 19, 2024

alright, got to at least fix some of the stuff --

  • fixed chrome support
  • fixed the par = vfs.all_vols[""] crash
  • added human-readable times to the shares listing
  • new separate login page for the shares, with a few less buttons and more appropriate text -- screenshot below
  • made the share creator a bit more intuitive

I posted a beta image on dockerhub, so you can pull copyparty/ac:beta if you wanna try it out :>

Screenshot_2024-08-19_21-51-29-or8

9001 added a commit that referenced this issue Aug 19, 2024
* crash when root volume is unmapped
* rephrase login-page for shares
* add chrome support (lol)
* fix confusing helptext
* improve ux
  * placeholders in share creator
  * button to disable expiration in share creator
  * human-readable timestamps in share listing
9001 added a commit that referenced this issue Aug 23, 2024
if files (one or more) are selected for sharing, then
a virtual folder is created to hold the selected files

if a single file is selected for sharing, then
the returned URL will point directly to that file

and fix some shares-related bugs:
* password coalescing
* log-spam on reload
@9001
Copy link
Owner

9001 commented Aug 23, 2024

should be better now, the only thing I didn't get around to is the buttons to increase the expiration time from the shares listing -- and there's the thing about up2k indexing blocking the creation of new shares, gonna have to think about that one... another time heh

as usual, let me know if you hit any issues :>

@9001 9001 closed this as completed Aug 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants