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

Create root account during installation #775

Open
josecelano opened this issue Nov 25, 2024 · 8 comments
Open

Create root account during installation #775

josecelano opened this issue Nov 25, 2024 · 8 comments

Comments

@josecelano
Copy link
Member

josecelano commented Nov 25, 2024

Relates to:

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

@Frontrider
Copy link

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.

@josecelano
Copy link
Member Author

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

  1. Predictable Setup Process:

    • Simplifies installation, especially in automated deployment scenarios, as the same credentials (or account) exist across all instances.
  2. Guaranteed Administrative Access:

    • Ensures that at least one admin account always exists, preventing situations where no admin is available due to accidental account deletion.
  3. Ease of Documentation:

    • Standardized username (e.g., "root") simplifies documentation and user guides for managing the system.
  4. Supports Recovery Scenarios:

    • Often used for emergency access in case other admin accounts are lost or misconfigured.

Cons

  1. Security Risks:

    • A predictable root account name (like "root") is a common attack target for brute force or credential-stuffing attacks.
  2. Reduced Flexibility:

    • Forces the presence of a specific account, which may not align with organizational policies or naming conventions.
  3. Difficult to Deactivate:

    • Even if disabled or unused, the account's presence can be seen as a security liability.
  4. Compliance Issues:

    • May conflict with security frameworks that require unique usernames and passwords or enforce dynamic account creation.

Creating Root Account During Installation

Pros

  1. Enhanced Security:

    • Allows administrators to create a unique username and strong password, reducing the predictability of attack targets.
  2. Better Customization:

    • Admins can configure the root account to align with organizational policies and security practices.
  3. Compliance Alignment:

    • More compatible with security standards that require unique usernames and dynamic account creation.
  4. Flexibility for Admins:

    • Allows organizations to start with their own custom administrator account, avoiding reliance on generic defaults.

Cons

  1. Risk of Misconfiguration:

    • If the installation process is not completed correctly, there is a risk of leaving the system without administrative access.
  2. Slightly More Complex Setup:

    • Adds extra steps to the installation process, which can slow down automated or scripted deployments.
  3. Recovery Challenges:

    • Without a predefined fallback root account, recovering administrative access might require manual intervention or database edits.
  4. 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.

@josecelano
Copy link
Member Author

josecelano commented Nov 25, 2024

Proposal 1

Since we don't have a Torrust Installer yet, I would propose the following:

  1. Add to the configuration new fields:
[auth]

[auth.root]
email = "admin@example.org"
password = "password"

NOTE: This section will be mandatory, and the password must be masked in output and logs.

  1. Add an option in the admin panel to grant another user the admin role.

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.

@josecelano
Copy link
Member Author

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 root account exists
        • If the root account exists -> does nothing
        • If the root account does not exist -> create the root account with the given password.
    • If the env var is not provided -> do nothing

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.

@josecelano
Copy link
Member Author

josecelano commented Nov 25, 2024

Proposal 3

Proposed by @mickvandijke here.

Pros:

  • This allows normal users (users vie app UI) to customize root account without the sysadmin support.

Cons:

  • No option for automatic setups unless it is combined with proposal 2.

@josecelano
Copy link
Member Author

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 root account will be the unique admin the 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 Configuration torrust-compose#30
    • We could implement other registration methods like Single sign-on. In these cases you might need a root account 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 root password.
  • The root account can't be deleted.
  • Env vars used in the solution cannot use the prefix TORRUST_INDEX_CONFIG_OVERRIDE to 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:

  1. TORRUST_INDEX_ROOT_PASSWORD is 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.1 root account already exists -> Show error and stop the application
    1.1.2 root account does not exist -> Create the root account with the given password
  2. TORRUST_INDEX_ROOT_PASSWORD not provided
    1.1 Check if the root account exists
    1.1.1 root account already exists -> Do nothing
    1.1.2 root account 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_password when 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 root account 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
  1. TORRUST_INDEX_RESET_ROOT_PASSWORD is not provided -> start application normally
  2. TORRUST_INDEX_RESET_ROOT_PASSWORD is provided
    1.1 Check if the root account exists
    1.1.1 root account does not exist -> show error and stop the application
    1.1.2 root account 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

@josecelano
Copy link
Member Author

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

@Frontrider
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants