oxyno-zeta / s3-proxy

S3 Reverse Proxy with GET, PUT and DELETE methods and authentication (OpenID Connect and Basic Auth)
https://oxyno-zeta.github.io/s3-proxy/
Apache License 2.0
292 stars 33 forks source link

OIDC: no resource declared message when it is #378

Closed fostermi closed 1 year ago

fostermi commented 1 year ago

Let me start by saying this looks like a really cool project and I can benefit from it greatly. However, I must say I've struggled to get the most simplistic implementation of this working. The documentation is a little terse and the "Example" page is just the main configuration file will all the options commented out. It'd be more helpful if there were more working examples with those options (I've introduced errors trying to un-comment lines and messing up the YAML).

That being said, I can get OIDC working with the "Target List" just fine. However, navigating to paths in that list seem to be ignoring the authorization piece. I keep getting the message in the debug logs:

level=debug msg="no resource found in authorization, means that authentication was skipped => skip authorization too"

However, I do have a resource declared in the Target Map.

# Targets map
targets:
  first-bucket:
     mount:
        path:
          - /usr/local/buckets/
        resources:
         - path: /
           methods:
             - GET
           provider: provider1
           oidc:
             authorizationAccesses: # Authorization accesses : groups or email or regexp
               - group: "Roles - My Group"
        actions:
         GET:
           enabled: true
           config:
             redirectWithTrailingSlashForNotFoundFile: true

I apologize for submitting a bug report here, but I don't see another way to communicate with the maintaners here in a discussion. I'm at a lost why this isn't working.

BONUS Question: Can someone enlighten me on what a "Mount" and "Path" is in this and the Target List context? It seems to be required but if the mounts in the Target List and Target Map are the same, you get an error. I don't see the container creating and mounting any files to the mount point, so I'm not sure what the purpose of them are, except to change the URL path when accessing the server in the browser.

oxyno-zeta commented 1 year ago

Hello @fostermi ,

That's the good place, no worry.

Ok there is 2 questions here. I will answer to both of them.

"Mount" and "Path": Mount and Path are for the web server. It is the same thing as in NGinX Location or Apache2 Virtual Host. So Mount is the structure configuration that will declare the Host and Path on which the server will answer for that specific target. Path is the url path on which the target will answer. Without any Host, it will listen on all domains. Example 1:

targets:
  first-bucket:
     mount:
        path:
          - /

So when you will call on http://localhost:8080/ or http://127.0.0.1:8080/ that will answer with the target results.

Example 2:

targets:
  first-bucket:
     mount:
       host: fake:8080
        path:
          - /base/

So when you will call on http://fake:8080/base/ that will answer with the target results.

Is it better now ?

Resources: This is because you only declared that path "/" under resource. So you are "protected" just when you go on "/" but not for any other path. If you want to be protected on path you must change your configuration like this one:

# Targets map
targets:
  first-bucket:
     mount:
        path:
          - /bucket/
        resources:
         - path: /bucket/*
           methods:
             - GET
           provider: provider1
           oidc:
             authorizationAccesses: # Authorization accesses : groups or email or regexp
               - group: "Roles - My Group"

Note: For your need of example configuration, there is some things under "Feature guide" (Example with API feature here ). Having more is really time consuming as you can imagine.

Feel free to ask anything again :)

Oxyno-zeta

fostermi commented 1 year ago

Ok, thanks for the clarification, regarding the term Mount. Its really more like application context-root or as you said "Location".

I tried your suggestion for the Target configuration, but I'm still getting the "no resource found in authorization" message, even though the mount path and the resource path are the same with a wildcard for everything under the path:

# Targets map
targets:
  first-bucket:
     mount:
        path:
          - /bucket/
        resources:
          - path: /bucket/*
            methods:
              - GET
            provider: provider1
            oidc:
              authorizationAccesses: 
                - group: "Roles - My Group"
        actions:
          GET:
            enabled: true
            config:
              redirectWithTrailingSlashForNotFoundFile: true
fostermi commented 1 year ago

Ok, I think I figured it out. The issue is that when un-commenting the lines from your full config file example, I preserved the line indentations, (i.e. I deleted the # and re-spaced the line by two). Thus resources was a child of mount instead of being at the same level.

# Targets map
targets:
  first-bucket:
     mount:
      path:
        - /buckets/
     resources:
       - path: /buckets/*
         methods:
           - GET
         provider: provider1
         oidc:
           authorizationAccesses: 
             - group: "Roles - MODS - Web Support"
     actions:
       GET:
         enabled: true
         config:
           redirectWithTrailingSlashForNotFoundFile: true

That's one of the things I mentioned by having an commented out file as your example.

One final thing. Why can't I have the Target list and Target map both start with /? If I do, the app crashes with:

panic: chi: attempting to Mount() a handler on an existing path, '/'
fostermi commented 1 year ago

Also, what does this mean in the logs:

"No GET hook declared for target first-bucket"
oxyno-zeta commented 1 year ago

Cool ! I'm happy to see that.

One final thing. Why can't I have the Target list and Target map both start with /? If I do, the app crashes with.... : You can't have them on the same path and any host. You have to select at least a host for both of them. Why ? Because how can the server router know that you want to access the target list or the target ? It's exactly the same thing as having 2 houses on same road with the same number. Which one do you pick ? Tell me if this isn't clear :) . I can give you an configuration example.

"No GET hook declared for target first-bucket": This message is printed in the log because you haven't declared any webhook on GET requests. It is a feature described here: https://oxyno-zeta.github.io/s3-proxy/feature-guide/webhooks/ if you want to look a it. It is optional ;)

fostermi commented 1 year ago

Ok, thanks for the response. I read the concept of the Target List as a sort of Directory Listing of all of the targets under the Target mount/path (or location or whatever you want to call it). Therefore it wasn't intuitive to think of Target list and Target as separate, but instead like a normal directory/file structure. That is, if I made a request to the root path /, I'd want a "listing" of everything under that URL. If I accessed an object under the root path, I'd obviously have to reference that object like /object hence no collision. I can't think of an use case for accessing a base mount point (or path or whatever) that wasn't a listing, since the request wouldn't refer to an actual object. If you think about typical Apache or Nginx routing, a Location block defines the public URL for the resource, which might include a Directory statement that defines it somewhere on disk, but you access it by the URL in the Location block. You don't use the Location to get a listing, then request an item in the filesystem by referring to its Directory location. Hence my confusion.

oxyno-zeta commented 1 year ago

Now everything is clear and is working well ?

fostermi commented 1 year ago

Yes, things are working. Thanks!