console1984 icon indicating copy to clipboard operation
console1984 copied to clipboard

Add password protection in console sessions

Open ashhadsheikh opened this issue 1 year ago • 6 comments

It currently asks for a name to log info, but with multiple folks having access any one can use anyone's name. Would be great to have a password issued to each user so they can use to only login using their password.

ashhadsheikh avatar Feb 26 '24 13:02 ashhadsheikh

I was just thinking about this. I don't think console1984 should provide its own authentication mechanism, but it would be nice to be able to plug an existing authentication mechanism. Maybe something like this?

config.console1984.user_authentication = proc do
  username = Console1984.supervisor.current_username # this will use the configured username resolver or ask for a username as needed
  user = User.find_by(username: username)
  raise "Invalid username" if user.nil?
  password = $stdin.getpass("Password: ")
  raise "Invalid password" unless user.valid_password?(password)
  raise "Not an admin" unless user.is_admin?
end

Then console1984 would call the user_authentication callable if it's set, or keep the current behavior if not.

This is a just a rough example, but I'd be happy to submit a PR if the maintainers would be open to such a feature. @jorgemanrubia wdyt?

olivier-thatch avatar Apr 16 '24 21:04 olivier-thatch

I like the idea @olivier-thatch 👍

jorgemanrubia avatar Apr 22 '24 08:04 jorgemanrubia

@olivier-thatch I'm also interested in this functionality. Has any progress been made yet?

mark-kraemer avatar May 01 '24 15:05 mark-kraemer

No, sorry, I've been very busy with an ongoing project and probably won't get a chance to work on this in the next few weeks.

olivier-thatch avatar May 01 '24 16:05 olivier-thatch

No worries! Completely understand. I have a workaround by configuring a custom session_logger that handles the password check

mark-kraemer avatar May 01 '24 18:05 mark-kraemer

I temporarily override the gem to handle it with Devise users

module Console1984
  class Supervisor
    def current_username
      if Console1984.config.ask_for_user_if_empty
        unless @current_username.present?
          email = ask_for_value "Please, enter your email"
          user = ::User.find_by(email: email)
          return raise Console1984::Errors::MissingUsername unless user.present?
          password = ask_for_value "Password: "
          return raise Console1984::Errors::MissingUsername unless user.valid_password? password
        end
        @current_username ||= user.email
      else
        @current_username ||= username_resolver.current.presence || handle_empty_username
      end
    end

    private
    def handle_empty_username
      if Console1984.config.ask_for_username_if_empty
        ask_for_value "Please, enter your name:"
      else
        raise Console1984::Errors::MissingUsername
      end
    end
  end

  class Config
    remove_const(:PROPERTIES) if (defined?(PROPERTIES))

    PROPERTIES = %i[
      session_logger username_resolver ask_for_username_if_empty shield command_executor
      protected_environments protected_urls
      production_data_warning enter_unprotected_encryption_mode_warning enter_protected_mode_warning
      incinerate incinerate_after incineration_queue
      protections_config
      base_record_class
      debug test_mode
      ask_for_user_if_empty
    ]
  
    attr_accessor(*PROPERTIES)

    private
    def set_defaults
      super
      self.ask_for_user_if_empty = false
    end
  end

  class Shield
    private
    def prevent_invoking_protected_methods
      Console1984::ProtectionsConfig.new(YAML.safe_load(File.read(Console1984::Engine.root.join("config/protections.yml"))).symbolize_keys)
    end
  end
end

Console1984.config.ask_for_username_if_empty = false
Console1984.config.ask_for_user_if_empty = true

marcelino056 avatar Jul 24 '24 15:07 marcelino056