enable Bcrypt password storage
This commit is contained in:
@@ -34,6 +34,7 @@ requires:
|
|||||||
Dancer: 1.3112
|
Dancer: 1.3112
|
||||||
Dancer::Plugin::Auth::Extensible: 0.3
|
Dancer::Plugin::Auth::Extensible: 0.3
|
||||||
Dancer::Plugin::DBIC: 0.1803
|
Dancer::Plugin::DBIC: 0.1803
|
||||||
|
Dancer::Plugin::Passphrase: 2
|
||||||
File::ShareDir: 1.03
|
File::ShareDir: 1.03
|
||||||
Guard: 1.022
|
Guard: 1.022
|
||||||
HTML::Parser: 3.7
|
HTML::Parser: 3.7
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ requires 'Daemon::Control' => 0.001000;
|
|||||||
requires 'Dancer' => 1.3112;
|
requires 'Dancer' => 1.3112;
|
||||||
requires 'Dancer::Plugin::DBIC' => 0.1803;
|
requires 'Dancer::Plugin::DBIC' => 0.1803;
|
||||||
requires 'Dancer::Plugin::Auth::Extensible' => 0.30;
|
requires 'Dancer::Plugin::Auth::Extensible' => 0.30;
|
||||||
|
requires 'Dancer::Plugin::Passphrase' => 2.00;
|
||||||
requires 'File::ShareDir' => 1.03;
|
requires 'File::ShareDir' => 1.03;
|
||||||
requires 'Guard' => 1.022;
|
requires 'Guard' => 1.022;
|
||||||
requires 'HTML::Parser' => 3.70;
|
requires 'HTML::Parser' => 3.70;
|
||||||
|
|||||||
@@ -99,9 +99,9 @@ $bool = $term->ask_yn(
|
|||||||
);
|
);
|
||||||
deploy_db() if $bool;
|
deploy_db() if $bool;
|
||||||
|
|
||||||
|
say '';
|
||||||
my $users = schema('netdisco')->resultset('User');
|
my $users = schema('netdisco')->resultset('User');
|
||||||
if ($users->count == 0) {
|
if ($users->count == 0) {
|
||||||
say '';
|
|
||||||
$bool = $term->ask_yn(
|
$bool = $term->ask_yn(
|
||||||
prompt => 'Would you like a default web user with Admin rights (discover, etc)?',
|
prompt => 'Would you like a default web user with Admin rights (discover, etc)?',
|
||||||
default => 'n',
|
default => 'n',
|
||||||
@@ -136,6 +136,10 @@ if ($users->count == 0) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
elsif (!setting('safe_password_store')) {
|
||||||
|
say '*** WARNING: Weak password hashes are being stored in the database! ***';
|
||||||
|
say '*** WARNING: Please add "safe_password_store: true" to your ~/environments/deployment.yml file. ***';
|
||||||
|
}
|
||||||
|
|
||||||
say '';
|
say '';
|
||||||
$bool = $term->ask_yn(
|
$bool = $term->ask_yn(
|
||||||
|
|||||||
@@ -210,7 +210,8 @@ C<name>, C<host>, C<user> and C<pass>).
|
|||||||
|
|
||||||
In the same file uncomment and edit the C<domain_suffix> setting to be
|
In the same file uncomment and edit the C<domain_suffix> setting to be
|
||||||
appropriate for your local site. If this is a fresh install, uncomment and set
|
appropriate for your local site. If this is a fresh install, uncomment and set
|
||||||
the C<no_auth> value to true (temporarily disables user authentication).
|
the C<no_auth> value to true (temporarily disables user authentication). Have
|
||||||
|
a quick read of the other settings to make sure you're happy, then move on.
|
||||||
|
|
||||||
=head1 Bootstrap
|
=head1 Bootstrap
|
||||||
|
|
||||||
@@ -243,7 +244,7 @@ daemon at the same time. Similarly, if you use the device discovery with
|
|||||||
Netdisco 2, disable your system's cron jobs for the Netdisco 1.x poller.
|
Netdisco 2, disable your system's cron jobs for the Netdisco 1.x poller.
|
||||||
|
|
||||||
At this point you can revisit the C<~/environments/deployment.yml> file to
|
At this point you can revisit the C<~/environments/deployment.yml> file to
|
||||||
uncomment more configuration. Check out the community string settings, and
|
uncomment more configuration. Enable the C<community> string settings, and
|
||||||
C<housekeeping> which enables the automatic periodic device discovery. See
|
C<housekeeping> which enables the automatic periodic device discovery. See
|
||||||
L<Configuration|App::Netdisco::Manual::Configuration> for further details.
|
L<Configuration|App::Netdisco::Manual::Configuration> for further details.
|
||||||
|
|
||||||
|
|||||||
@@ -223,6 +223,13 @@ Value: List of Modules. Default: Empty List.
|
|||||||
List of additional L<App::Netdisco::Web::Plugin> names to load. See also the
|
List of additional L<App::Netdisco::Web::Plugin> names to load. See also the
|
||||||
C<web_plugins> setting.
|
C<web_plugins> setting.
|
||||||
|
|
||||||
|
=head3 C<safe_password_store>
|
||||||
|
|
||||||
|
Value: Boolean. Default: true.
|
||||||
|
|
||||||
|
Set to "C<false>" if you MUST maintain backwards compatibility with the Netdisco
|
||||||
|
1.x web interface. Strongly recommended that you leave this set to "C<true>".
|
||||||
|
|
||||||
=head2 Netdisco Core
|
=head2 Netdisco Core
|
||||||
|
|
||||||
=head3 C<mibhome>
|
=head3 C<mibhome>
|
||||||
|
|||||||
@@ -90,61 +90,6 @@ hook 'after' => sub {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
get qr{^/(?:login(?:/denied)?)?} => sub {
|
|
||||||
template 'index';
|
|
||||||
};
|
|
||||||
|
|
||||||
# Override default login_handler so that we can log access in the
|
|
||||||
# database
|
|
||||||
post '/login' => sub {
|
|
||||||
my ($success, $realm) = authenticate_user(
|
|
||||||
params->{username}, params->{password}
|
|
||||||
);
|
|
||||||
if ($success) {
|
|
||||||
session logged_in_user => params->{username};
|
|
||||||
session logged_in_user_realm => $realm;
|
|
||||||
|
|
||||||
schema('netdisco')->resultset('UserLog')->create({
|
|
||||||
username => session('logged_in_user'),
|
|
||||||
userip => request->remote_address,
|
|
||||||
event => "Login",
|
|
||||||
details => params->{return_url},
|
|
||||||
});
|
|
||||||
|
|
||||||
redirect params->{return_url} || uri_for('/');
|
|
||||||
} else {
|
|
||||||
|
|
||||||
schema('netdisco')->resultset('UserLog')->create({
|
|
||||||
username => params->{username},
|
|
||||||
userip => request->remote_address,
|
|
||||||
event => "Login Failure",
|
|
||||||
details => params->{return_url},
|
|
||||||
});
|
|
||||||
|
|
||||||
vars->{login_failed}++;
|
|
||||||
forward uri_for('/login'), { login_failed => 1 }, { method => 'GET' };
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
# Since we override the default login_handler, logout has to be handled as
|
|
||||||
# well
|
|
||||||
any ['get','post'] => '/logout' => sub {
|
|
||||||
|
|
||||||
schema('netdisco')->resultset('UserLog')->create({
|
|
||||||
username => session('logged_in_user'),
|
|
||||||
userip => request->remote_address,
|
|
||||||
event => "Logout",
|
|
||||||
details => '',
|
|
||||||
});
|
|
||||||
|
|
||||||
session->destroy;
|
|
||||||
if (params->{return_url}) {
|
|
||||||
redirect params->{return_url};
|
|
||||||
} else {
|
|
||||||
return "OK, logged out successfully.";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
any qr{.*} => sub {
|
any qr{.*} => sub {
|
||||||
var('notfound' => true);
|
var('notfound' => true);
|
||||||
status 'not_found';
|
status 'not_found';
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use base 'Dancer::Plugin::Auth::Extensible::Provider::Base';
|
|||||||
|
|
||||||
use Dancer ':syntax';
|
use Dancer ':syntax';
|
||||||
use Dancer::Plugin::DBIC;
|
use Dancer::Plugin::DBIC;
|
||||||
|
use Dancer::Plugin::Passphrase;
|
||||||
use Digest::MD5;
|
use Digest::MD5;
|
||||||
|
|
||||||
sub authenticate_user {
|
sub authenticate_user {
|
||||||
@@ -77,8 +77,25 @@ sub match_with_local_pass {
|
|||||||
|
|
||||||
return unless $password and $user->$password_column;
|
return unless $password and $user->$password_column;
|
||||||
|
|
||||||
|
if ($user->$password_column !~ m/^{[A-Z]+}/) {
|
||||||
|
debug 'authN: using legacy MD5';
|
||||||
my $sum = Digest::MD5::md5_hex($password);
|
my $sum = Digest::MD5::md5_hex($password);
|
||||||
return ($sum eq $user->$password_column ? 1 : 0);
|
|
||||||
|
if ($sum eq $user->$password_column) {
|
||||||
|
if (setting('safe_password_store')) {
|
||||||
|
# upgrade password if successful, and permitted
|
||||||
|
$user->update({password => passphrase($password)->generate});
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
debug 'authN: using Passphrase';
|
||||||
|
return passphrase($password)->matches($user->$password_column);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub match_with_ldap {
|
sub match_with_ldap {
|
||||||
|
|||||||
@@ -27,4 +27,59 @@ hook 'before' => sub {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
get qr{^/(?:login(?:/denied)?)?} => sub {
|
||||||
|
template 'index';
|
||||||
|
};
|
||||||
|
|
||||||
|
# override default login_handler so we can log access in the database
|
||||||
|
post '/login' => sub {
|
||||||
|
my ($success, $realm) = authenticate_user(
|
||||||
|
params->{username}, params->{password}
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($success) {
|
||||||
|
session logged_in_user => params->{username};
|
||||||
|
session logged_in_user_realm => $realm;
|
||||||
|
|
||||||
|
schema('netdisco')->resultset('UserLog')->create({
|
||||||
|
username => session('logged_in_user'),
|
||||||
|
userip => request->remote_address,
|
||||||
|
event => "Login",
|
||||||
|
details => params->{return_url},
|
||||||
|
});
|
||||||
|
|
||||||
|
redirect params->{return_url} || uri_for('/');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
schema('netdisco')->resultset('UserLog')->create({
|
||||||
|
username => params->{username},
|
||||||
|
userip => request->remote_address,
|
||||||
|
event => "Login Failure",
|
||||||
|
details => params->{return_url},
|
||||||
|
});
|
||||||
|
|
||||||
|
vars->{login_failed}++;
|
||||||
|
forward uri_for('/login'), { login_failed => 1 }, { method => 'GET' };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
# we override the default login_handler, so logout has to be handled as well
|
||||||
|
any ['get','post'] => '/logout' => sub {
|
||||||
|
|
||||||
|
schema('netdisco')->resultset('UserLog')->create({
|
||||||
|
username => session('logged_in_user'),
|
||||||
|
userip => request->remote_address,
|
||||||
|
event => "Logout",
|
||||||
|
details => '',
|
||||||
|
});
|
||||||
|
|
||||||
|
session->destroy;
|
||||||
|
if (params->{return_url}) {
|
||||||
|
redirect params->{return_url};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return "OK, logged out successfully.";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
true;
|
true;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use Dancer ':syntax';
|
|||||||
use Dancer::Plugin::Ajax;
|
use Dancer::Plugin::Ajax;
|
||||||
use Dancer::Plugin::DBIC;
|
use Dancer::Plugin::DBIC;
|
||||||
use Dancer::Plugin::Auth::Extensible;
|
use Dancer::Plugin::Auth::Extensible;
|
||||||
|
use Dancer::Plugin::Passphrase;
|
||||||
|
|
||||||
use App::Netdisco::Web::Plugin;
|
use App::Netdisco::Web::Plugin;
|
||||||
use Digest::MD5 ();
|
use Digest::MD5 ();
|
||||||
@@ -21,6 +22,16 @@ sub _sanity_ok {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub _make_password {
|
||||||
|
my $pass = (shift || passphrase->generate_random);
|
||||||
|
if (setting('safe_password_store')) {
|
||||||
|
return passphrase($pass)->generate;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return Digest::MD5::md5_hex($pass),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ajax '/ajax/control/admin/users/add' => require_role admin => sub {
|
ajax '/ajax/control/admin/users/add' => require_role admin => sub {
|
||||||
send_error('Bad Request', 400) unless _sanity_ok();
|
send_error('Bad Request', 400) unless _sanity_ok();
|
||||||
|
|
||||||
@@ -28,7 +39,7 @@ ajax '/ajax/control/admin/users/add' => require_role admin => sub {
|
|||||||
my $user = schema('netdisco')->resultset('User')
|
my $user = schema('netdisco')->resultset('User')
|
||||||
->create({
|
->create({
|
||||||
username => param('username'),
|
username => param('username'),
|
||||||
password => Digest::MD5::md5_hex(param('password')),
|
password => _make_password(param('password')),
|
||||||
fullname => param('fullname'),
|
fullname => param('fullname'),
|
||||||
ldap => (param('ldap') ? \'true' : \'false'),
|
ldap => (param('ldap') ? \'true' : \'false'),
|
||||||
port_control => (param('port_control') ? \'true' : \'false'),
|
port_control => (param('port_control') ? \'true' : \'false'),
|
||||||
@@ -56,7 +67,7 @@ ajax '/ajax/control/admin/users/update' => require_role admin => sub {
|
|||||||
|
|
||||||
$user->update({
|
$user->update({
|
||||||
((param('password') ne '********')
|
((param('password') ne '********')
|
||||||
? (password => Digest::MD5::md5_hex(param('password')))
|
? (password => _make_password(param('password')))
|
||||||
: ()),
|
: ()),
|
||||||
fullname => param('fullname'),
|
fullname => param('fullname'),
|
||||||
ldap => (param('ldap') ? \'true' : \'false'),
|
ldap => (param('ldap') ? \'true' : \'false'),
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ web_plugins:
|
|||||||
- Device::Neighbors
|
- Device::Neighbors
|
||||||
- Device::Addresses
|
- Device::Addresses
|
||||||
extra_web_plugins: []
|
extra_web_plugins: []
|
||||||
|
safe_password_store: true
|
||||||
|
|
||||||
# -------------
|
# -------------
|
||||||
# NETDISCO CORE
|
# NETDISCO CORE
|
||||||
|
|||||||
@@ -18,6 +18,11 @@ database:
|
|||||||
# RECOMMENDED SETTINGS
|
# RECOMMENDED SETTINGS
|
||||||
# --------------------
|
# --------------------
|
||||||
|
|
||||||
|
# set to "false" if you MUST maintain backwards compatibility
|
||||||
|
# with Netdisco 1.x web frontend.
|
||||||
|
# ```````````````````````````````````````````````````````````
|
||||||
|
safe_password_store: true
|
||||||
|
|
||||||
# will be stripped from fqdn when displayed in the web UI
|
# will be stripped from fqdn when displayed in the web UI
|
||||||
# also, do not forget the leading dot.
|
# also, do not forget the leading dot.
|
||||||
# ```````````````````````````````````````````````````````
|
# ```````````````````````````````````````````````````````
|
||||||
@@ -48,8 +53,8 @@ database:
|
|||||||
# expiry:
|
# expiry:
|
||||||
# when: '20 23 * * *'
|
# when: '20 23 * * *'
|
||||||
|
|
||||||
# increase the performance of parallel DNS resolution for node names
|
# increase the performance of parallel DNS resolution for node
|
||||||
# (the default is max_outstanding: 10)
|
# names (the default is max_outstanding: 10)
|
||||||
|
# ````````````````````````````````````````````````````````````
|
||||||
#dns:
|
#dns:
|
||||||
# max_outstanding: 100
|
# max_outstanding: 100
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user