Giter Site home page Giter Site logo

Comments (24)

kaysond avatar kaysond commented on May 14, 2024 1

@JaneJeon what you are describing seems like a configuration/permissions issue, not a container issue. Once I set proper write permissions on the data directory (e.g. chown -R 10001 /data && chmod -R u+w /data), the container started up with no issues.

I do think, though, that the way the container is set up is prone to confuse users because permissions handling is fairly opaque. It would probably be better overall to make it compatible with docker-compose user: or allow for PUID and PGID env vars to set the process user/group.

from lldap.

kaysond avatar kaysond commented on May 14, 2024 1

I'm happy to work on that next after we close #89!

from lldap.

kaysond avatar kaysond commented on May 14, 2024

So it was sort of a permissions issue - originally I was getting a different error that lldap couldn't write to /data/private_key, because the directory wasn't writeable by 10001. So I did a touch private_key && chmod a+w private_key. Apparently the library (opaque?) doesn't like it if the private_key file exists but is empty!

from lldap.

nitnelave avatar nitnelave commented on May 14, 2024

I see. And you didn't have issues with the users.db, users.db.shm and related files?

I'll try to add a more explicit (and fatal) error if we can't write to the server key.

from lldap.

kaysond avatar kaysond commented on May 14, 2024

I see. And you didn't have issues with the users.db, users.db.shm and related files?

No. The order of events was:

  1. Run container without write permissions on /data
  2. Get "Error: Could not write the generated server setup to file /data/private_key"
  3. Run touch private_key && chmod a+w private_key
  4. Get "Error: This error results from an error during password verification"
  5. Remove private_key, and do chown 10001 /data

Then everything starts up just fine because it can create files in /data, and there's no empty private_key.

from lldap.

kaysond avatar kaysond commented on May 14, 2024

So now I'm trying to run it as a different user (via docker-compose user:) so I can use the existing permissions setup of my storage, and I get the following:

Loading configuration from /data/lldap_config.toml
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Could not write the generated server setup to file `server_key`

Caused by:
    Permission denied (os error 13)', server/src/infra/configuration.rs:218:49
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

It's interesting because it says its loading the configuration, and it has permissions to read that file, but it's using what appears to be the default value for key_file

Edit: looks like the issue here is that get_server_setup automatically writes to the location at key_file if the path doesn't exist, and since the first call to ConfigurationBuilder is used to build the defaults, it's trying to write to /app/server_key, which my user doesn't have permissions for
https://github.com/nitnelave/lldap/blob/ba7848d043da20041c14312bd4d0ea24107b8623/server/src/infra/configuration.rs#L217-L222
https://github.com/nitnelave/lldap/blob/ba7848d043da20041c14312bd4d0ea24107b8623/server/src/infra/configuration.rs#L80-L93
https://github.com/nitnelave/lldap/blob/ba7848d043da20041c14312bd4d0ea24107b8623/server/src/infra/configuration.rs#L105-L121

from lldap.

kaysond avatar kaysond commented on May 14, 2024

This also explains the original error I was seeing - the problem is that get_server_setup sees that the private_key file exists, so it loads it, but then provides a totally empty config to the rest of the program. I think there probably needs to be some validation to ensure there are no problems with the file contents before continuing.

from lldap.

JaneJeon avatar JaneJeon commented on May 14, 2024

I, too, am also stuck on the

Get "Error: Could not write the generated server setup to file /data/private_key"

thing (not just touching the file, but also creating a valid private key and directly mounting it on it, in which case it complains that it can't read it). I'm pretty sure there's some deep underlying permissions issue at play here.

Tried like 50000 different things (including different directories and permissions) :/

from lldap.

JaneJeon avatar JaneJeon commented on May 14, 2024

And given how severe this issue is (it's preventing me from even spinning up the container in the first place) and given that nobody apparently complained about this before us, I'm guessing it's a somewhat recent regression. If that's the case, when would be the last "safe" image?

from lldap.

JaneJeon avatar JaneJeon commented on May 14, 2024

As I have mentioned above, I have run those commands that you mentioned and it still doesn't work. I've ran it within the container and I thought maybe the issue is that I"m mounting the data directory from the outside (i.e. I'm mounting from a host folder to /data within the directory), but even after I have run the commands on the host folder I'm mounting, it stil spits out the same error.

Either way, I'm ready to throw in the towel. I host like 7 different docker containers that I mount a host directory onto, and lldap seems to be the only one absolutely screeching at it.

from lldap.

JaneJeon avatar JaneJeon commented on May 14, 2024

btw @nitnelave I'm pretty sure I found where the actual error message came from: https://docs.rs/opaque-ke/0.5.0/opaque_ke/errors/enum.ProtocolError.html#variant.VerificationError

Dunno if it helps, but

from lldap.

kaysond avatar kaysond commented on May 14, 2024

btw @nitnelave I'm pretty sure I found where the actual error message came from: https://docs.rs/opaque-ke/0.5.0/opaque_ke/errors/enum.ProtocolError.html#variant.VerificationError

Dunno if it helps, but

Is that the error message you're seeing? Your comment mentioned the other error. If you're getting the password verification error it's probably the same thing I saw - whatever you've put in the private_key file is invalid.

I also mount a host directory (/var/lib/lldap/data) to /data in the container. If I empty the directory (rm /var/lib/lldap/data/*) then give the default user perms (chown 10001 + chmod /var/lib/lldap/data), it works.

from lldap.

JaneJeon avatar JaneJeon commented on May 14, 2024

Okay, just checked again. I had generated a valid pem key but it looks like having any key in there triggers the error you mentioned above.

Deleting it seems to work, but it's still... idk, quite dirty of a solution imho

from lldap.

nitnelave avatar nitnelave commented on May 14, 2024

Yeah, I'm aware that the permissions stuff is not super well handled right now. I think I'll build on #89 and introduce better user support, including the docker-compose user, UID and so on. I'll have to look up how it's done elsewhere, unless someone wants to take it up.

from lldap.

nitnelave avatar nitnelave commented on May 14, 2024

That would be of great help, thanks!

from lldap.

kaysond avatar kaysond commented on May 14, 2024

So what linuxserver.io does in their containers, is create a user called abc, and in their base image init scripts, do usermod -o -u "$PUID" abc (and similar for groups). They then do exec s6-setuidgid abc:abc in the container to drop privileges on the process.

You could do something similar here, though you don't have busybox setuidgid in alpine, or s6 (you could add it to the container, though). I think you should be able to just do it with su but I haven't tried that yet.

But if we fix the initial server_key write bug, you could just use docker's built in user parameter. What I'd propose is to change the default for key_file to be /data/server_key, and database_url to sqlite:///data/users.db?mode=rwc (which would match the config template anyways). Then in the container we make a /data directory with 0777 permissions.

This way, the initial config can get written there no problem if you don't set the user, or if you set key_file to another location. If you mount a host directory, then the container will see the permissions of the host directory.

I did a quick test and it seems to work just fine, and by doing --user I can set the process uid to whatever I want

from lldap.

nitnelave avatar nitnelave commented on May 14, 2024

Rather than change the defaults in the source code, how about this: the start script checks if /data/lldap_config.toml exists, otherwise it creates it (copying from the template). That way we can make sure that the folder is writeable even before we start lldap.
WDYT?

from lldap.

kaysond avatar kaysond commented on May 14, 2024

Rather than change the defaults in the source code, how about this: the start script checks if /data/lldap_config.toml exists, otherwise it creates it (copying from the template). That way we can make sure that the folder is writeable even before we start lldap.
WDYT?

I think thats a good idea in general, but it doesnt quite solve the permissions problem. The problem is you're running the lldap binary from inside /app. So when configuration.rs tries to write the initial key file to server_key, it actually writes it to /app/server_key, which is owned by the app user (uid 10001). If you set --user, then it can't write there and it crashes. It always tries to write there when you start the container up when it loads the defaults

Maybe the "right" thing to do here is actually fix the "bug" - we don't actually want get_server_setup to write the server config to file until after the defaults are loaded, the toml is merged, and the env vars are merged

https://github.com/nitnelave/lldap/blob/ba7848d043da20041c14312bd4d0ea24107b8623/server/src/infra/configuration.rs#L115

from lldap.

nitnelave avatar nitnelave commented on May 14, 2024

But... It does wait until the config is loaded. It's just that in the cases mentioned above, there was no (readable) config to load, so it reverted to the defaults. I think it's better to make sure there's a config, and if it's copied from the template it'll have the correct location for the server_key file

from lldap.

kaysond avatar kaysond commented on May 14, 2024

I'm new to rust, so its very possible I'm reading the code wrong, but this is my understanding of configuration.rs

init gets called
https://github.com/nitnelave/lldap/blob/5b5395103ae56ebbea841be76c000b8b243895dc/server/src/infra/configuration.rs#L206

This creates the configuration, which starts with a call to ConfigurationBuilder::default().build().unwrap() on L128, then afterwards merges in the config file and env vars

https://github.com/nitnelave/lldap/blob/5b5395103ae56ebbea841be76c000b8b243895dc/server/src/infra/configuration.rs#L217-L222

The initial ConfigurationBuilder::build() calls get_server_setup(self.key_file.as_deref().unwrap_or("server_key"))?; (L82) but at this point, self.key_file has not yet been defined from the config file, so it's using "server_key" from either the unwrap_or or from the macro (again - rust noob so not sure which, but theyre the same value!)

https://github.com/nitnelave/lldap/blob/5b5395103ae56ebbea841be76c000b8b243895dc/server/src/infra/configuration.rs#L80-L84

Macro:

https://github.com/nitnelave/lldap/blob/5b5395103ae56ebbea841be76c000b8b243895dc/server/src/infra/configuration.rs#L63-L64

So the result is that get_server_setup("server_key") is called, and since /app/server_key doesn't exist, it tries to write there. If the process uid is not 10001, this will always fail.

https://github.com/nitnelave/lldap/blob/5b5395103ae56ebbea841be76c000b8b243895dc/server/src/infra/configuration.rs#L105-L121

After the defaults are loaded as described above, user-supplied values get merged in, and then there's another call to get_server_setup, but this time its with correctly loaded value of key_file (assuming you can even get here).

https://github.com/nitnelave/lldap/blob/5b5395103ae56ebbea841be76c000b8b243895dc/server/src/infra/configuration.rs#L228


This lines up with the behavior I observed - the config file was properly mounted and readable just fine, but if i changed --user, it would fail trying to write to server_key, despite that in the config file I set key_file: /data/private_key.

Please let me know if my rust understanding is off :D

from lldap.

nitnelave avatar nitnelave commented on May 14, 2024

Don't sell yourself short, you're one up on me on this one :D

get_server_setup should not be called from the build, indeed. Right now, it tries to read/write 2 server keys, one next to the binary and one in the correct place.

I'll fix that when i get the chance.

from lldap.

kaysond avatar kaysond commented on May 14, 2024

get_server_setup should not be called from the build, indeed. Right now, it tries to read/write 2 server keys, one next to the binary and one in the correct place.

I'll fix that when i get the chance.

Awesome! I bet that, along with maybe some more explicit info on permissions in the docs should solve most of the issues

from lldap.

nitnelave avatar nitnelave commented on May 14, 2024

Just pushed a fix, feel free to try it, you can add user: 1000:1000 (or whatever your uid/gid is) in the docker compose.

from lldap.

kaysond avatar kaysond commented on May 14, 2024

This is fixed on my end. Thanks!

from lldap.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.