torrust-index
torrust-index copied to clipboard
Create `root` account during installation
Relates to:
- https://github.com/torrust/torrust-compose/issues/30
- https://github.com/torrust/torrust-index-gui/discussions/290
Context
Currently, the application allows only one admin user, the first registered user. That produces some known issues:
- Registration must be enabled at least temporarily until you create this account.
- For testing, there is no other way to grant a user the role
admin, so testing must be done directly in the database. - There can be only one admin
UPDATE: I moved the initial proposal to comment.
@da2ce7
I'd also say that on my side I also have an OIDC provider, and I can add claims to the jwt token as needed (so I could add "TORRUST_ADMIN" role to the token).
Very likely out of scope, but it may let this application get away with a simpler user management system by offloading it for the cases when you need more.
Here are the pros and cons of using a hardcoded root account (predefined during installation) versus creating a root/admin account dynamically during installation:
Other things to consider by ChatGPT:
Hardcoded Root Account
Pros
-
Predictable Setup Process:
- Simplifies installation, especially in automated deployment scenarios, as the same credentials (or account) exist across all instances.
-
Guaranteed Administrative Access:
- Ensures that at least one admin account always exists, preventing situations where no admin is available due to accidental account deletion.
-
Ease of Documentation:
- Standardized username (e.g., "root") simplifies documentation and user guides for managing the system.
-
Supports Recovery Scenarios:
- Often used for emergency access in case other admin accounts are lost or misconfigured.
Cons
-
Security Risks:
- A predictable root account name (like "root") is a common attack target for brute force or credential-stuffing attacks.
-
Reduced Flexibility:
- Forces the presence of a specific account, which may not align with organizational policies or naming conventions.
-
Difficult to Deactivate:
- Even if disabled or unused, the account's presence can be seen as a security liability.
-
Compliance Issues:
- May conflict with security frameworks that require unique usernames and passwords or enforce dynamic account creation.
Creating Root Account During Installation
Pros
-
Enhanced Security:
- Allows administrators to create a unique username and strong password, reducing the predictability of attack targets.
-
Better Customization:
- Admins can configure the root account to align with organizational policies and security practices.
-
Compliance Alignment:
- More compatible with security standards that require unique usernames and dynamic account creation.
-
Flexibility for Admins:
- Allows organizations to start with their own custom administrator account, avoiding reliance on generic defaults.
Cons
-
Risk of Misconfiguration:
- If the installation process is not completed correctly, there is a risk of leaving the system without administrative access.
-
Slightly More Complex Setup:
- Adds extra steps to the installation process, which can slow down automated or scripted deployments.
-
Recovery Challenges:
- Without a predefined fallback root account, recovering administrative access might require manual intervention or database edits.
-
Inconsistent Deployments:
- In environments with many installations, dynamic creation can lead to inconsistencies in credentials or account naming.
Recommendation
- For single-instance or highly secure environments: Prefer creating a root/admin account during installation to improve security and align with best practices.
- For automated deployments or recoverability focus: A hardcoded root account is advantageous but should be accompanied by robust measures like forced password changes, 2FA, or immediate account blocking post-installation.
Proposal 1
Since we don't have a Torrust Installer yet, I would propose the following:
- Add to the configuration new fields:
[auth]
[auth.root]
email = "[email protected]"
password = "password"
NOTE: This section will be mandatory, and the password must be masked in output and logs.
- Add an option in the admin panel to grant another user the
adminrole.
This depends on other features, like improving user management. You need to find the user. In the first version, the root user or other admin users can load a concrete URL to grant the admin role to other users. But we can discuss how to implement it on the GUI repo.
Proposal 2
Instead of using the configuration, we can pass an env var TORRUST_INDEX_ROOT_PASSWORD.
When you run the index:
- Check if the env var is provided
- If it's provided
- Check if the
rootaccount exists- If the
rootaccount exists -> does nothing - If the
rootaccount does not exist -> create therootaccount with the given password.
- If the
- Check if the
- If the env var is not provided -> do nothing
- If it's provided
The sysadmin (installer) can run the index with the env var.
Pros:
- The password will not be stored in the configuration
- You can automate deployments with the env var
This would be like a minimal installer where installation settings are provided via env vars instead of via the app UI.
Proposal 3
- Build a minimal installer assistant. See https://github.com/torrust/torrust-index-gui/discussions/290
- The sysamdin is not responsible for setting up the account
- The first user can setup the app via the web interface
Proposed by @mickvandijke here.
Pros:
- This allows normal users (users vie app UI) to customize
rootaccount without the sysadmin support.
Cons:
- No option for automatic setups unless it is combined with proposal 2.
Generic considerations for all proposals
- The solution must be valid for:
- Automatic deployments/setup: if you want to start a new environment automatically.
- Installer: if we have an installer in the future. The installer should be able to ask the user for the root password during the installation.
- Testing: for testing, we should be able to pre-generate the password or have an easy way to get it after running the test environment.
- This
rootaccount will be the uniqueadminthe application officially supports now. In the future, it will be a "superadmin". It might have some rights admins don't have, and some special characteristics, like it can't be deleted. - Some special cases have to be considered in order to design a good solution:
- Registration can be disabled. The only way to create the admin account now is to register the user, so if you want to disable registration, you need to temporarily enable it to create the admin account. See https://github.com/torrust/torrust-compose/issues/30
- We could implement other registration methods like Single sign-on. In these cases you might need a
rootaccount to perfom some actions even if you are not included in the third-party user directory.
- The sysadmin (who does the infrastructure setup) is the only one who can have access to this
rootpassword. - The
rootaccount can't be deleted. - Env vars used in the solution cannot use the prefix
TORRUST_INDEX_CONFIG_OVERRIDEto avoid collisions with the static global configuration.
Proposal 4 (GitLab)
This is a more elaborated version of proposal 3 based on how GitLab does it.
Set the root password
We use the env var TORRUST_INDEX_ROOT_PASSWORD.
TORRUST_INDEX_ROOT_PASSWORD="strong password" torrust-index
When you run the index, you can pass that env var. The index will:
TORRUST_INDEX_ROOT_PASSWORDis provided 1.1 Password is empty or not strong -> Show error and stop the application 1.2 Password is NOT empty and strong 1.1 Check if the root account exists 1.1.1rootaccount already exists -> Show error and stop the application 1.1.2rootaccount does not exist -> Create the root account with the given passwordTORRUST_INDEX_ROOT_PASSWORDnot provided 1.1 Check if the root account exists 1.1.1rootaccount already exists -> Do nothing 1.1.2rootaccount does not exist -> Create the root account with a strong random password and store it in./storage/index/etc/initial_root_password(/etc/torrust/index/initial_root_passwordwhen using default docker config).
The sysadmin (installer) can run the index with the env var.
NOTE:
- This can be used in production and testing.
- A strong password definition is included in password constraints in the configuration.
- If the random password was generated in
./storage/index/etc/initial_root_password, it's removed automatically after 24 hours. - If the sysadmin installing the application is worried about passing the secret via env var, it can avoid including the command in the history and also stop the application and restart it after creating the
rootaccount to remove the env var.
Reset the root password
In the first iteration, we can implement it by restarting the service. In the future, we could have a console client like GitLab to reset the root password.
You can stop the application and restart it using this env var:
TORRUST_INDEX_RESET_ROOT_PASSWORD="new strong password" torrust-index
TORRUST_INDEX_RESET_ROOT_PASSWORDis not provided -> start application normallyTORRUST_INDEX_RESET_ROOT_PASSWORDis provided 1.1 Check if the root account exists 1.1.1rootaccount does not exist -> show error and stop the application 1.1.2rootaccount exists 1.1.2.1 Password is empty or not strong -> Show error and stop the application 1.1.2.1 Password is strong -> Change password an continue
NOTE:
- This is not needed in testing environments.
cc @da2ce7
I'd also say that on my side I also have an OIDC provider, and I can add claims to the jwt token as needed (so I could add "TORRUST_ADMIN" role to the token).
Very likely out of scope, but it may let this application get away with a simpler user management system by offloading it for the cases when you need more.
Hi @Frontrider, If I understand correctly, your proposal is adding a claim with the role. We already have the admin flag because we only have two roles:
pub struct UserCompact {
pub user_id: UserId,
pub username: String,
pub administrator: bool,
}
But we don't rely on that info for authorization. We use the token only for authentication.
If we want to support that in the future, I guess we have to make some changes like:
- Enable/disable third-party authentication/authorization
- Use the role info in the jwt token in the authorization service instead of the local database.
I don't understand when you would refresh the user's role. In the simplest implementation, it is done only when the users log in.
FYI, we are using casbin for authorization, but it's not exposed via our public API.
cc @da2ce7 @mario-nt
Hi @Frontrider, If I understand correctly, your proposal is adding a claim with the role.
Yeah, if it remains that simple then just let me tell you what value to look for in the claim. The tokens I have on an internal network have an array with the items being the roles (in this case look for an "admin" string inside that array), but on a different setup with Cognito I could just give it an "is_admin" claim. (may not be reasonable, as I'd have other roles in the token too)
So yeah, give me some way to set that boolean from my id token.