Skip to content

Commit 56dafbc

Browse files
committed
Enable configdb to be run on same server as database
1 parent 1db24f8 commit 56dafbc

File tree

3 files changed

+147
-67
lines changed

3 files changed

+147
-67
lines changed

bin/configdb.pl

+41-7
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,11 @@
2323
use FindBin;
2424
use lib "$FindBin::Bin/../lib";
2525

26+
use Brass::Actions ();
2627
use Brass::ConfigDB;
28+
use Brass::Schema;
2729
use Getopt::Long;
30+
use YAML qw/LoadFile/;
2831
use Term::ReadKey;
2932

3033
my ($server, $type, $action, $param, $use, %update, $namespace, $pass);
@@ -42,19 +45,39 @@
4245
# Stop here when loaded by a test script
4346
return 1 if caller();
4447

48+
# Assume this is running on the same server as the brass database if the web
49+
# server directory exists
50+
my $is_local = -d '/srv/Brass';
51+
4552
my $sshpass = $ENV{SSHPASS};
46-
if (!defined $sshpass)
53+
if (!$is_local && !defined $sshpass)
4754
{
4855
# Get passphrase of user's SSH key, do not echo
49-
ReadMode ('noecho');
50-
print "Please enter the passphrase:\n";
51-
$sshpass = <STDIN>;
52-
chomp $sshpass;
56+
my $sshpass = _get_passphrase("Please enter the passphrase of the local SSH key:");
5357
$ENV{SSHPASS} = $sshpass;
54-
ReadMode ('normal');
5558
}
5659

57-
my $cdb = Brass::ConfigDB->new;
60+
my ($pwdpass, $schema);
61+
if ($is_local && $type eq 'pwd')
62+
{
63+
# If we are running directly on the server, get passphrase to
64+
# ecnrypt/decrypt passwords (this is kept locally in /.configdb if
65+
# accessing the database remotely)
66+
$pwdpass = _get_passphrase("Please enter the passphrase for password encyrption and decryption:");
67+
68+
# Get direct connection from database - not needed for running on remote
69+
# server
70+
my $config_file = '/srv/Brass/config.yml';
71+
-f $config_file
72+
or error __x"Unable to find config file {file}", file => $config_file;
73+
my $config = LoadFile $config_file;
74+
my $db_config = $config->{plugins}->{DBIC}->{default};
75+
my @connect = ($db_config->{dsn}, $db_config->{user}, $db_config->{password}, $db_config->{options});
76+
77+
$schema = Brass::Schema->connect(@connect);
78+
}
79+
80+
my $cdb = Brass::ConfigDB->new(is_local => $is_local, schema => $schema);
5881

5982
my $ret = $cdb->run(
6083
server => $server,
@@ -66,6 +89,17 @@
6689
use => $use,
6790
update => \%update,
6891
sshpass => $sshpass,
92+
pwdpass => $pwdpass,
6993
);
7094

7195
print "$ret\n";
96+
97+
sub _get_passphrase
98+
{ my $prompt = shift;
99+
ReadMode ('noecho');
100+
print "$prompt\n";
101+
$sshpass = <STDIN>;
102+
chomp $sshpass;
103+
ReadMode ('normal');
104+
$sshpass;
105+
}

lib/Brass/API.pm

+8-60
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ package Brass::API;
2121
use strict; use warnings;
2222

2323
use Brass::Actions ();
24+
use Brass::ConfigDB;
2425
use Crypt::Blowfish;
25-
use Crypt::CBC;
2626
use Crypt::JWT qw(decode_jwt);
2727
use Crypt::PK::ECC;
2828
use Dancer2 appname => 'Brass';
@@ -79,10 +79,7 @@ hook before => sub {
7979
var payload => $client;
8080
};
8181

82-
sub randompw()
83-
{ my $pwgen = CtrlO::Crypt::XkcdPassword->new;
84-
$pwgen->xkcd( words => 3, digits => 2 );
85-
}
82+
my $cdb = Brass::ConfigDB->new(is_local => 1, schema => schema);
8683

8784
get 'api/pwd/' => sub {
8885
my $user = var 'api_user'
@@ -93,63 +90,14 @@ get 'api/pwd/' => sub {
9390
my $passphrase = var('payload')->{passphrase}
9491
or error __"Need passphrase for retrieving and setting passwords";
9592

96-
my $server = query_parameters->get('server')
97-
or error __"Please specify server";
98-
99-
my $action = query_parameters->get('action')
100-
or error __"Need required action";
101-
102-
Brass::Actions::is_allowed_action($action)
103-
or error __x"Invalid action: {action}", action => $action;
104-
105-
my $param = query_parameters->get('param');
106-
!Brass::Actions::action_requires_pwd($action) || $param
107-
or error __x"Please specify required username for {action} password",
108-
action => $action;
109-
110-
my ($username) = $schema->resultset('Pw')->search({
111-
'server.name' => $server,
112-
'me.username' => $param,
113-
'me.type' => $action,
114-
},{
115-
join => 'server',
116-
});
117-
118-
my $cipher = Crypt::CBC->new(
119-
-key => $passphrase,
120-
-cipher => 'Blowfish'
93+
my $pass = $cdb->run_pwd(
94+
server => query_parameters->get('server'),
95+
pass => query_parameters->get('pass'),
96+
action => query_parameters->get('action'),
97+
param => query_parameters->get('param'),
98+
pwdpass => $passphrase,
12199
);
122100

123-
my $pass = query_parameters->get('pass');
124-
if (defined $pass) {
125-
# check password is strong
126-
my $pwcheck = Data::Password::Check->check({
127-
password => $pass,
128-
tests => [qw(length silly repeated)]
129-
});
130-
if ($pwcheck->has_errors) {
131-
error __"Please use a secure password, provided password is not secure : " .
132-
join(',', @{ $pwcheck->error_list });
133-
}
134-
}
135-
if ($username) {
136-
# update password if new one provided
137-
if ($pass) {
138-
my $pw = $cipher->encrypt($pass);
139-
$username->pwencrypt($pw);
140-
$username->update();
141-
}
142-
else {
143-
$pass = $cipher->decrypt($username->pwencrypt);
144-
}
145-
}
146-
else {
147-
$pass //= randompw;
148-
my $pw = $cipher->encrypt($pass);
149-
my $s = $schema->resultset('Server')->find_or_create({ name => $server });
150-
my $u = $schema->resultset('Pw')->create({ server_id => $s->id, username => $param, pwencrypt => $pw, type => $action });
151-
$pass = $cipher->decrypt($u->pwencrypt);
152-
}
153101
content_type 'application/json';
154102
encode_json({
155103
"is_error" => 0,

lib/Brass/ConfigDB.pm

+98
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,37 @@ use CtrlO::Crypt::XkcdPassword;
3030
use URI;
3131
use URI::QueryParam;
3232

33+
has is_local => (
34+
is => 'ro',
35+
);
36+
37+
has schema => (
38+
is => 'ro',
39+
);
40+
3341
sub run
42+
{ my ($self, %params) = @_;
43+
44+
return $self->_run_local(%params)
45+
if $self->is_local;
46+
47+
$self->_run_remote(%params);
48+
}
49+
50+
sub _run_local
51+
{ my ($self, %params) = @_;
52+
53+
my $type = delete $params{type}
54+
or error __"Please provide type of request with --type";
55+
56+
# XXX More types to be migrated
57+
if ($type eq 'pwd')
58+
{
59+
$self->run_pwd(%params);
60+
}
61+
}
62+
63+
sub _run_remote
3464
{ my ($self, %params) = @_;
3565

3666
my $server = $params{server};
@@ -159,6 +189,74 @@ sub run
159189
}
160190
}
161191

192+
sub run_pwd
193+
{ my ($self, %params) = @_;
194+
195+
my $server = $params{server}
196+
or error __"Please specify server";
197+
198+
my $action = $params{action}
199+
or error __"Need required action";
200+
201+
Brass::Actions::is_allowed_action($action)
202+
or error __x"Invalid action: {action}", action => $action;
203+
204+
my $param = $params{param};
205+
206+
!Brass::Actions::action_requires_pwd($action) || $param
207+
or error __x"Please specify required username for {action} password",
208+
action => $action;
209+
210+
my $pwdpass = $params{pwdpass}
211+
or error __"Please provide the password encryption passphrase";
212+
213+
my ($username) = $self->schema->resultset('Pw')->search({
214+
'server.name' => $server,
215+
'me.username' => $param,
216+
'me.type' => $action,
217+
},{
218+
join => 'server',
219+
});
220+
221+
my $cipher = Crypt::CBC->new(
222+
-key => $pwdpass,
223+
-cipher => 'Blowfish'
224+
);
225+
226+
my $pass = $params{pass};
227+
if (defined $pass) {
228+
# check password is strong
229+
my $pwcheck = Data::Password::Check->check({
230+
password => $pass,
231+
tests => [qw(length silly repeated)]
232+
});
233+
if ($pwcheck->has_errors) {
234+
error __"Please use a secure password, provided password is not secure : " .
235+
join(',', @{ $pwcheck->error_list });
236+
}
237+
}
238+
if ($username) {
239+
# update password if new one provided
240+
if ($pass) {
241+
my $pw = $cipher->encrypt($pass);
242+
$username->pwencrypt($pw);
243+
$username->update();
244+
}
245+
else {
246+
$pass = $cipher->decrypt($username->pwencrypt);
247+
}
248+
}
249+
else {
250+
$pass //= randompw();
251+
my $pw = $cipher->encrypt($pass);
252+
my $s = $self->schema->resultset('Server')->find_or_create({ name => $server });
253+
my $u = $self->schema->resultset('Pw')->create({ server_id => $s->id, username => $param, pwencrypt => $pw, type => $action });
254+
$pass = $cipher->decrypt($u->pwencrypt);
255+
}
256+
257+
return $pass;
258+
}
259+
162260
sub randompw()
163261
{ my $pwgen = CtrlO::Crypt::XkcdPassword->new;
164262
$pwgen->xkcd( words => 3, digits => 2 );

0 commit comments

Comments
 (0)