mirror of
https://github.com/librenms/librenms.git
synced 2024-10-07 16:52:45 +00:00
Two-factor UI config and status display (#13012)
* two-factor UI config and status display additions * force test re-run * removal of blade foreach via keyBy * remove where clause against all() * attempt where filtering with keyBy * use @config and getPref in blade * another forgotten @config changed Co-authored-by: PipoCanaja <38363551+PipoCanaja@users.noreply.github.com>
This commit is contained in:
@@ -54,7 +54,7 @@ class UserController extends Controller
|
||||
$this->authorize('manage', User::class);
|
||||
|
||||
return view('user.index', [
|
||||
'users' => User::orderBy('username')->get(),
|
||||
'users' => User::with('preferences')->orderBy('username')->get(),
|
||||
'multiauth' => User::query()->distinct('auth_type')->count('auth_type') > 1,
|
||||
]);
|
||||
}
|
||||
|
@@ -36,6 +36,10 @@ class UserPref extends BaseModel
|
||||
// ---- Helper Functions ----
|
||||
public static function getPref(User $user, $pref)
|
||||
{
|
||||
if ($user->relationLoaded('preferences')) {
|
||||
return optional($user->preferences->firstWhere('pref', $pref))->value;
|
||||
}
|
||||
|
||||
return $user->preferences()->where('pref', $pref)->value('value');
|
||||
}
|
||||
|
||||
|
@@ -1,28 +1,29 @@
|
||||
source: Extensions/Two-Factor-Auth.md
|
||||
path: blob/master/doc/
|
||||
|
||||
# About
|
||||
# Two-Factor Authentication
|
||||
|
||||
Over the last couple of years, the primary attack vector for internet
|
||||
accounts has been static passwords. Therefore static passwords are no
|
||||
longer sufficient to protect unauthorized access to accounts. Two
|
||||
Factor Authentication adds a variable part in authentication
|
||||
procedures. A user is now required to supply a changing 6-digit
|
||||
passcode in addition to it's password to obtain access to the account.
|
||||
passcode in addition to their password to obtain access to the account.
|
||||
|
||||
LibreNMS has a RFC4226 conform implementation of both Time and Counter
|
||||
LibreNMS has a RFC4226 conformant implementation of both Time and Counter
|
||||
based One-Time-Passwords. It also allows the administrator to
|
||||
configure a throttle time to enforce after 3 failures exceeded. Unlike
|
||||
RFC4226 suggestions, this throttle time will not stack on the amount of failures.
|
||||
RFC4226 suggestions, this throttle time will not stack on the amount of
|
||||
failures.
|
||||
|
||||
# Types
|
||||
## Types
|
||||
|
||||
In general, these two types do not differ in algorithmic terms.
|
||||
The types only differ in the variable being used to derive the passcodes from.
|
||||
The underlying HMAC-SHA1 remains the same for both types, security
|
||||
advantages or disadvantages of each are discussed further down.
|
||||
|
||||
## Timebased One-Time-Password (TOTP)
|
||||
### Timebased One-Time-Password (TOTP)
|
||||
|
||||
Like the name suggests, this type uses the current Time or a subset of
|
||||
it to generate the passcodes. These passcodes solely rely on the
|
||||
@@ -32,7 +33,7 @@ given time, presumably the time upon login. RFC4226 suggests a
|
||||
resynchronization attempt in case the passcode mismatches, providing
|
||||
the attacker a range of up to +/- 3 Minutes to create passcodes.
|
||||
|
||||
## Counterbased One-Time-Password (TOTP)
|
||||
### Counterbased One-Time-Password (HOTP)
|
||||
|
||||
This type uses an internal counter that needs to be in sync with the
|
||||
server's counter to successfully authenticate the passcodes. The main
|
||||
@@ -42,25 +43,51 @@ passcodes. RFC4226 suggests a resynchronization attempt in case the
|
||||
passcode mismatches, providing the attacker a range of up to +4
|
||||
increments from the actual counter to create passcodes.
|
||||
|
||||
# Configuration
|
||||
## Configuration
|
||||
|
||||
### WebUI
|
||||
|
||||
Enable 'Two-Factor' Via Global Settings in the Web UI under
|
||||
Authentication -> General Authentication Settings.
|
||||
|
||||
Optionally enter a throttle timer in seconds. This will unlock an account
|
||||
after this time once it has failed 3 attempt to authenticate. Set to 0 (default)
|
||||
to disable this feature, meaning accounts will remain locked after 3 attempts
|
||||
and will need an administrator to clear.
|
||||
|
||||
### CLI
|
||||
|
||||
Enable Two-Factor:
|
||||
|
||||
```php
|
||||
$config['twofactor'] = true;
|
||||
```
|
||||
`./lnms config:set twofactor true`
|
||||
|
||||
|
||||
Set throttle-time (in seconds):
|
||||
|
||||
```php
|
||||
$config['twofactor_lock'] = 300;
|
||||
```
|
||||
`./lnms config:set twofactor_lock 300`
|
||||
|
||||
# Usage
|
||||
## User Administation
|
||||
|
||||
These steps imply that TwoFactor has been enabled in your `config.php`
|
||||
If Two-Factor is enabled, the Settings -> Manage Users grid will show a '2FA' column
|
||||
containing a green tick for users with active 2FA.
|
||||
|
||||
Create a Two-Factor key:
|
||||
There is no functionality to mandate 2FA for users.
|
||||
|
||||
If a user has failed 3 attempts, their account can be unlocked or 2FA disabled by
|
||||
editing the user from the Manage Users table.
|
||||
|
||||
If a throttle timer is set, it will unlock accounts after this time. If set to the
|
||||
default of 0, accounts will need to be manually unlocked by an administrator after 3
|
||||
failed attempts.
|
||||
|
||||
Locked accounts will report to the user stating to wait for the throttle time period,
|
||||
or to contact the administrator if no timer set.
|
||||
|
||||
## End-User Enrolment
|
||||
|
||||
These steps imply that Two-Factor has been enabled system wide as above under Configuration.
|
||||
|
||||
2FA is enabled by each user once they are logged in normally:
|
||||
|
||||
- Go to 'My Settings' (/preferences/)
|
||||
- Choose TwoFactor type
|
||||
@@ -68,12 +95,24 @@ Create a Two-Factor key:
|
||||
- If your browser didn't reload, reload manually
|
||||
- Scan provided QR or click on 'Manual' to see the Key
|
||||
|
||||
## Google Authenticator
|
||||
### Google Authenticator
|
||||
|
||||
Installation guides for Google Authenticator can be found [here](https://support.google.com/accounts/answer/1066447?hl=en).
|
||||
|
||||
Usage:
|
||||
|
||||
- Create a key like described above
|
||||
- Scan provided QR or click on 'Manual' and type down the Secret
|
||||
- Create a key as described above
|
||||
- Scan provided QR or click on 'Manual' and enter the Secret
|
||||
- On next login, enter the passcode that the App provides
|
||||
|
||||
### LastPass Authenticator
|
||||
|
||||
LastPass Authenticator is confirmed to work with Timebased One-Time Passwords (TOTP).
|
||||
|
||||
Installation guide for LastPass Authenticator can be found [here](https://support.logmeininc.com/lastpass/help/lastpass-authenticator-lp030014).
|
||||
|
||||
Usage:
|
||||
|
||||
- Create a Timerbased key as described above
|
||||
- Click Add (+) and scan provided QR or click on 'NO QR CODE?' and enter naming details and the Secret
|
||||
- On next login, enter the passcode that the App provides
|
||||
|
@@ -620,7 +620,7 @@
|
||||
"units": "days",
|
||||
"group": "auth",
|
||||
"section": "general",
|
||||
"order": 3,
|
||||
"order": 4,
|
||||
"type": "integer"
|
||||
},
|
||||
"authlog_purge": {
|
||||
@@ -3737,7 +3737,7 @@
|
||||
"default": "Unauthorised access or use shall render the user liable to criminal and/or civil prosecution.",
|
||||
"group": "auth",
|
||||
"section": "general",
|
||||
"order": 4,
|
||||
"order": 5,
|
||||
"type": "text"
|
||||
},
|
||||
"mac_oui.enabled": {
|
||||
@@ -4220,7 +4220,7 @@
|
||||
"type": "integer",
|
||||
"group": "auth",
|
||||
"section": "general",
|
||||
"order": 5
|
||||
"order": 6
|
||||
},
|
||||
"peering_descr": {
|
||||
"default": [
|
||||
@@ -4670,7 +4670,7 @@
|
||||
"default": false,
|
||||
"group": "auth",
|
||||
"section": "general",
|
||||
"order": 6,
|
||||
"order": 7,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rancid_ignorecomments": {
|
||||
@@ -5203,11 +5203,19 @@
|
||||
"order": 1
|
||||
},
|
||||
"twofactor": {
|
||||
"default": "false",
|
||||
"type": "boolean",
|
||||
"group": "auth",
|
||||
"section": "general",
|
||||
"order": 1
|
||||
},
|
||||
"twofactor_lock": {
|
||||
"default": "0",
|
||||
"type": "integer",
|
||||
"group": "auth",
|
||||
"section": "general",
|
||||
"order": 2
|
||||
},
|
||||
"unix-agent-connection-time-out": {
|
||||
"default": 10,
|
||||
"type": "integer"
|
||||
|
@@ -1331,6 +1331,14 @@ return [
|
||||
'traceroute6' => [
|
||||
'description' => 'Path to traceroute6',
|
||||
],
|
||||
'twofactor' => [
|
||||
'description' => 'Two-Factor',
|
||||
'help' => 'Allow users to activate and use Timebased (TOTP) or Counterbased (HOTP) One-Time Passwords (OTP)',
|
||||
],
|
||||
'twofactor_lock' => [
|
||||
'description' => 'Two-Factor Throttle Time (seconds)',
|
||||
'help' => 'Lock-out time to wait in seconds before allowing further attempts if Two-Factor authentication is failed 3 times consecutively - will prompt user to wait this long. Set to 0 to disable resulting in a permanent account lock-out and a message to user to contact administrator',
|
||||
],
|
||||
'unix-agent' => [
|
||||
'connection-timeout' => [
|
||||
'description' => 'Unix-agent connection timeout',
|
||||
|
@@ -22,6 +22,9 @@
|
||||
@if(\LibreNMS\Authentication\LegacyAuth::getType() == 'mysql')
|
||||
<th data-column-id="enabled" data-formatter="enabled">@lang('Enabled')</th>
|
||||
@endif
|
||||
@config('twofactor')
|
||||
<th data-column-id="twofactor" data-formatter="twofactor">@lang('2FA')</th>
|
||||
@endconfig
|
||||
<th data-column-id="descr">@lang('Description')</th>
|
||||
<th data-column-id="action" data-formatter="actions" data-sortable="false" data-searchable="false">@lang('Actions')</th>
|
||||
</tr>
|
||||
@@ -38,6 +41,11 @@
|
||||
@if(\LibreNMS\Authentication\LegacyAuth::getType() == 'mysql')
|
||||
<td>{{ $user->enabled }}</td>
|
||||
@endif
|
||||
@config('twofactor')
|
||||
@if(app('App\Models\UserPref')->getPref($user, 'twofactor'))
|
||||
<td>1</td>
|
||||
@endif
|
||||
@endconfig
|
||||
<td>{{ $user->descr }}</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
@@ -62,6 +70,11 @@
|
||||
return '<span class="fa fa-fw fa-close text-danger"></span>';
|
||||
}
|
||||
},
|
||||
twofactor: function (column, row) {
|
||||
if(row['twofactor'] == 1) {
|
||||
return '<span class="fa fa-fw fa-check text-success"></span>';
|
||||
}
|
||||
},
|
||||
actions: function (column, row) {
|
||||
var edit_button = '<form action="{{ route('users.edit', ':user_id') }}'.replace(':user_id', row['user_id']) + '" method="GET">' +
|
||||
'@csrf' +
|
||||
|
Reference in New Issue
Block a user