diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a9bb4d..dafd4a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,16 +49,17 @@ This is the initial release of `muscl`. ### Known deviations from `mysql-admutils`' behaviour - `--help` output is formatted by clap in a different style. -- `mysql-dbadm edit-perm` uses the new privilege editor implementation. Replicating - the old behaviour - there shoulnd't have been any (or at least very few) scripts relying on the old - command API or behavior. -- The new tools use the new implementation to find it's configuration file, and uses the - new configuration format. See the example config and installation instructions for more - information about how to configure the software. -- The order in which input is validated (e.g. whether you own a user, whether the - contains illegal characters, whether the user does or does not exist) might be different - from the original program, leading to the same command reporting different errors. -- Arguments are de-duplicated, meaning that if you run something like +- `mysql-dbadm edit-perm` uses the new privilege editor implementation. The formatting that + was used in `mysql-admutils` is no longer present. However, since the editor is purely an + interactive tool, there shouldn't have been any scripts relying on the old formatting. +- The configuration file is shared for all variants of the program, and `muscl` will use + its new logic to look for and parse this file. See the example config and + [installation instructions][installation-instructions] for more information about how to + configure the software. +- The order in which input is validated might be differ from the original + (e.g. database ownership checks, invalid character checks, existence checks, ...). + This means that running the exact same command might lead to different error messages. +- Command-line arguments are de-duplicated. For example, if the user runs `mysql-dbadm create user_db1 user_db2 user_db1`, the program will only try to create - the `user_db1` once. The old program would attempt to create it twice, failing the second time. + the `user_db1` once. The old program would have attempted to create it twice, + failing the second attempt. diff --git a/README.md b/README.md index e3ff1db..c41573f 100644 --- a/README.md +++ b/README.md @@ -3,26 +3,30 @@ # muscl 💪 -Dropping DBs (dumbbells) and having mysql spasms since 2024 +Dropping DBs (dumbbells) and having MySQL spasms since 2024 ## What is this? -This is a CLI tool that let's unprivileged users perform administrative operations on a MySQL DBMS, given the are authorized to perform the action on the database or database user in question. -The default authorization mechanism is to only let the user perform these actions on databases and database users that are prefixed with their username, -or with the name of any unix group that the user is a part of. i.e. `_mydb`, `_mydbuser`, or `_myotherdb`. +`muscl is a secure MySQL administration tool for multi-user systems. +It allows unprivileged users to manage their own databases and database users without granting them direct access to the MySQL server. +Authorization is handled by a prefix-based model tied to Unix users and groups, making it ideal for shared hosting environments, like university servers, tilde servers, or similar. -The available administrative actions include: +When a user requests an administrative operation, the `muscl` daemon verifies authenticates the user through unix socket peer credentials, +and then checks the requested item name against the user's username and group list for authorization. +The default authorization mechanism only allows the user to manage items prefixed with either their username or a group name. +For example, a user would be allowed to manage items like `_mydb`, `_mydbuser`, or `_myotherdb`. + +The available administrative operations include: - creating/listing/modifying/deleting databases and database users - modifying privileges for a database user on a database - changing the passwords of the database users - locking and unlocking database users -- ... more to come +- ... and more -The software is designed to be run as a client and a server. The server has administrative access to the mysql server, -and is responsible for authorizing any requests from the clients. - -This software is designed for multi-user servers, like tilde servers, university servers, etc. +The software is designed to be run as a client and a server. The clients are run by the unprivileged users, +and does not have direct access to the MySQL server. Instead, they communicate with the muscl server +over a IPC, which then performs the requested operations on behalf of the clients. ## Documentation diff --git a/docs/compiling.md b/docs/compiling.md index 77006e3..36a3747 100644 --- a/docs/compiling.md +++ b/docs/compiling.md @@ -4,7 +4,8 @@ This document describes how to compile `muscl` from source code, along with othe ## Build -To just compile muscl, there is not many special steps needed. You need to have a working Rust toolchain installed. +To just compile `muscl`, there is not many special steps needed. +You need to have a working [Rust toolchain](https://www.rust-lang.org/tools/install) installed. ```bash # Compile in debug mode @@ -25,7 +26,7 @@ ls target/release-lto # muscl, mysql-dbadm, mysql-useradm, ... > [!NOTE] > This happens automatically when building the deb package, so you can skip this step if that's the goal. -In order to generate shell completions that work correctly, you want to put `muscl` (or alias symlinks) in your `$PATH`. +In order to generate shell completions that work correctly, you need to put `muscl` (or alias symlinks) in your `$PATH`. ```bash cargo build --release diff --git a/docs/development.md b/docs/development.md index 9106fc5..5c6ec02 100644 --- a/docs/development.md +++ b/docs/development.md @@ -1,14 +1,14 @@ # Development and testing -Ensure you have a [rust toolchain](https://www.rust-lang.org/tools/install) installed. +Ensure you have a [Rust toolchain](https://www.rust-lang.org/tools/install) installed. -In order to set up a test instance of mariadb in a docker container, run the following command: +In order to set up a test instance of MariaDB in a docker container, run the following command: ```bash docker run --rm --name mariadb -e MYSQL_ROOT_PASSWORD=secret -p 3306:3306 -d mariadb:latest ``` -This will start a mariadb instance with the root password `secret`, and expose the port 3306 on the host machine. +This will start a MariaDB instance with the root password `secret`, and expose the port 3306 on the host machine. Run the following command to create a configuration file with the default settings: @@ -16,10 +16,10 @@ Run the following command to create a configuration file with the default settin cp ./assets/example-config.toml ./config.toml ``` -If you used the docker command above, you can use these settings as is, but if you are running mariadb/mysql on another host, port or with another password, adjust the corresponding fields in `config.toml`. +If you used the docker command above, you can use these settings as is, but if you are running MariaDB/MySQL on another host, port or with another password, adjust the corresponding fields in `config.toml`. This file will contain your database password, but is ignored by git, so it will not be committed to the repository. -You should now be able to connect to the mariadb instance, after building the program and using arguments to specify the config file. +You should now be able to connect to the MariaDB instance, after building the program and using arguments to specify the config file. ```bash cargo run -- --config-file ./config.toml @@ -42,7 +42,8 @@ docker stop mariadb If you have nix installed, you can easily test your changes in a NixOS vm by running: ```bash -nix run .#vm +nix run .#vm # Start a NixOS VM in QEMU with muscl and MariaDB installed +nix run .#vm-mysql # Start a NixOS VM in QEMU with muscl and MySQL installed ``` You can configure the vm in `flake.nix` diff --git a/docs/installation.md b/docs/installation.md index ef01900..6c6f7b5 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -13,14 +13,14 @@ You can install muscl by adding the [PVV apt repository][pvv-apt-repository] and sudo -i # Check the version of your Debian installation -VERSION_CODENAME=$(lsb_release -cs) - -# Add the repository -echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/pvvgit-projects.asc] https://git.pvv.ntnu.no/api/packages/Projects/debian $VERSION_CODENAME main" | tee -a /etc/apt/sources.list.d/gitea.list +VERSION_CODENAME=$(. /etc/os-release && echo "$VERSION_CODENAME") # Pull the repository key curl https://git.pvv.ntnu.no/api/packages/Projects/debian/repository.key -o /etc/apt/keyrings/pvvgit-projects.asc +# Add the repository +echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/pvvgit-projects.asc] https://git.pvv.ntnu.no/api/packages/Projects/debian $VERSION_CODENAME main" | tee -a /etc/apt/sources.list.d/pvv-git.list + # Update package lists apt update @@ -28,31 +28,38 @@ apt update apt install muscl ``` +> [!NOTE] +> This has been tested on Debian 12 (bookworm) and Debian 13 (trixie) at the time of writing. + ## Creating a database user -In order for the daemon to be able to do anything interesting on the mysql server, it needs +In order for the daemon to be able to do anything interesting on the MySQL server, it needs a database user with sufficient privileges. You can create such a user by running the following commands -on the mysql server as the admin user (or another user with sufficient privileges): +on the MySQL server as the admin user (or another user with sufficient privileges): ```sql -CREATE USER `muscl`@`%` IDENTIFIED BY ''; -GRANT SELECT, INSERT, UPDATE, DELETE ON `mysql`.* TO `muscl`@`%`; -GRANT GRANT OPTION, CREATE, DROP ON *.* TO 'muscl'@'%'; +CREATE USER `muscl`@`localhost` IDENTIFIED BY ''; +GRANT SELECT, INSERT, UPDATE, DELETE ON `mysql`.* TO `muscl`@`localhost`; +GRANT GRANT OPTION, CREATE, DROP ON *.* TO `muscl`@`localhost`; FLUSH PRIVILEGES; ``` Make sure to remember the username and password, as we will now need to add them to the muscl configuration. +If your MySQL server is not running on the same host as the muscl server, you will need to replace `localhost` with the appropriate hostname or IP address in the different commands above. Alternatively, you can use `'%`' to allow connections from any host, but this is not recommended. + The configuration already comes preconfigured expecting the database user to be named `muscl`. If you named it differently, please edit `/etc/muscl/muscl.conf` accordingly. +muscl will use the `mysql` database to manage users and databases, and the `*.*` privileges to be able to create, drop and grant privileges on arbitrary databases (restricted by the prefix system). + For systemd-based setups, we recommend using `systemd-creds` to provide the database password, see the section below. -## Setting the myscl password ... +## Setting the MySQL password ... ### ... with `systemd-creds` -The debian package assumes that you will provide the password for `muscl`'s database user with `systemd-creds`. +The Debian package assumes that you will provide the password for `muscl`'s database user with `systemd-creds`. You can add the password like this: @@ -64,12 +71,16 @@ sudo -i mkdir -p /etc/credstore.encrypted systemd-creds setup -# Be careful not to leave the password in your shell history! -# Add a space before setting the next line to avoid this. - export MUSCL_MYSQL_PASSWORD="" +# Prompt for the muscl MySQL password +read -s MUSCL_MYSQL_PASSWORD +<... enter strong password here> -# Now set the muscl mysql password +# Now set the muscl MySQL password systemd-creds encrypt --name=muscl_mysql_password <(echo "$MUSCL_MYSQL_PASSWORD") /etc/credstore.encrypted/muscl_mysql_password + +# Restart the muscl service to pick up the new credential +systemctl daemon-reload +systemctl restart muscl.service ``` If you are running systemd older than version 254 (see `systemctl --version`), you might have to override the service to point to the path of the credential manually, because `ImportCredential=` is not supported. Run `systemctl edit muscl.service` and add the following lines: @@ -82,7 +93,7 @@ LoadCredentialEncrypted=muscl_mysql_password:/etc/credstore.encrypted/muscl_mysq ### ... without `systemd-creds` If you do not have systemd, or if you do not want to use `systemd-creds`, you can also set the password in any other file on the system. -Be careful to ensure that the file is not readable by unprivileged users, as it would yield them too much access to the mysql server. +Be careful to ensure that the file is not readable by unprivileged users, as it would yield them too much access to the MySQL server. Edit `/etc/muscl/muscl.conf` and set the `mysql_password_file` option below `[database]` to point to the file containing the password. If you are using systemd, you should also create an override to unset the `ImportCredential=` line. Run `systemctl edit muscl.service` and add the following lines: @@ -118,6 +129,6 @@ group:adm The muscl server will work with older versions of systemd, but the recommended version is 254 or newer. -For full landlock support (disabled by default), you need a linux kernel version 6.7 or newer. +For full landlock support (disabled by default), you need a Linux kernel version 6.7 or newer. [pvv-apt-repository]: https://git.pvv.ntnu.no/Projects/-/packages/debian/muscl diff --git a/docs/mysql-admutils-compatibility.md b/docs/mysql-admutils-compatibility.md index 632c33f..e33353b 100644 --- a/docs/mysql-admutils-compatibility.md +++ b/docs/mysql-admutils-compatibility.md @@ -1,6 +1,6 @@ # Compatibility mode with [mysql-admutils](https://git.pvv.ntnu.no/Projects/mysql-admutils) -If you enable the feature flag `mysql-admutils-compatibility` (enabled by default for now), the output directory will contain two symlinks to the `musl` binary: `mysql-dbadm` and `mysql-useradm`. When invoked through these symlinks, the binary will react to its `argv[0]` and behave accordingly. These modes strive to behave as similar as possible to the original programs. +If you enable the `mysql-admutils-compatibility` feature flag when [compiling][compiling] (enabled by default for now), the output directory will contain two symlinks to the `muscl` binary: `mysql-dbadm` and `mysql-useradm`. When you run either of the symlinks, the program will enter a compatibility mode that mimics the behaviour of the corresponding program from the `mysql-admutils` package. These tools try to replicate the behaviour of the original programs as closely as possible. ```bash cargo build @@ -8,21 +8,32 @@ cargo build ./target/debug/mysql-useradm --help ``` -These symlinks are also included in the deb packages. +These symlinks are also included in the deb packages by default. ### Known deviations from `mysql-admutils`' behaviour +There are some differences between the original programs and the compatibility mode in `muscl`. +The known ones are: + - `--help` output is formatted by clap in a different style. -- `mysql-dbadm edit-perm` uses the new privilege editor implementation. Replicating - the old behaviour - there shoulnd't have been any (or at least very few) scripts relying on the old - command API or behavior. -- The new tools use the new implementation to find it's configuration file, and uses the - new configuration format. See the example config and installation instructions for more - information about how to configure the software. -- The order in which input is validated (e.g. whether you own a user, whether the - contains illegal characters, whether the user does or does not exist) might be different - from the original program, leading to the same command reporting different errors. -- Arguments are de-duplicated, meaning that if you run something like +- `mysql-dbadm edit-perm` uses the new privilege editor implementation. The formatting that + was used in `mysql-admutils` is no longer present. However, since the editor is purely an + interactive tool, there shouldn't have been any scripts relying on the old formatting. +- The configuration file is shared for all variants of the program, and `muscl` will use + its new logic to look for and parse this file. See the example config and + [installation instructions][installation-instructions] for more information about how to + configure the software. +- The order in which input is validated might be differ from the original + (e.g. database ownership checks, invalid character checks, existence checks, ...). + This means that running the exact same command might lead to different error messages. +- Command-line arguments are de-duplicated. For example, if the user runs `mysql-dbadm create user_db1 user_db2 user_db1`, the program will only try to create - the `user_db1` once. The old program would attempt to create it twice, failing the second time. + the `user_db1` once. The old program would have attempted to create it twice, + failing the second attempt. + +One detail that might be considered a difference but, is that the compatibility mode supports +command line completions when the user presses tab. This is not a feature of the original programs, +but it does not change any of the previous behaviour either. + +[compiling]: ./compiling.md +[installation-instructions]: ./installation.md diff --git a/docs/nixos.md b/docs/nixos.md index 79b6802..c602e11 100644 --- a/docs/nixos.md +++ b/docs/nixos.md @@ -1,6 +1,6 @@ # Use with NixOS -For NixOS, there is a module available via the nix flake. You can include it in your configuration like this: +For NixOS, there is a NixOS module available in the nix flake. You can include it in your configuration like this: ```nix {