Automatically handle cookie signing keys

Which will get renewed every 24 hours. Remove the now useless cookie section of the config
This commit is contained in:
Daniel Berteaud 2015-06-29 19:09:28 +02:00
parent c8d6bde2de
commit 14b6298d77
7 changed files with 74 additions and 26 deletions

View File

@ -51,12 +51,6 @@ credentials = 'rest'
; Default to 0
;demo = 0
[cookie]
; Secret passphrase used to sign cookies. You must set this
;secret = '1zEewX24ZD%2RvtF%e'
; Cookie name, You shouldn't have to change this
;name = 'vroom'
[rooms]
; After this amount of time in minutes, rooms without any activity will be purged
;inactivity_timeout = '60'

View File

@ -6,7 +6,15 @@ CREATE TABLE `config` (
UNIQUE (`key`)
) ENGINE INNODB DEFAULT CHARSET=utf8;
INSERT INTO `config` (`key`,`value`)
VALUES ('schema_version', '6');
VALUES ('schema_version', '7');
CREATE TABLE `session_keys` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`key` VARCHAR(160) NOT NULL,
`date` DATETIME NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
INDEX (`date`)
) ENGINE INNODB DEFAULT CHARSET=utf8;
CREATE TABLE `rooms` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,

View File

@ -32,8 +32,6 @@ sub get_conf(){
$config->{'interface.template'} ||= 'default';
$config->{'interface.chrome_extension_id'} ||= 'ecicdpoejfllflombfanbhfpgcimjddn';
$config->{'interface.chrome_extension_id'} ||= 0;
$config->{'cookie.secret'} ||= 'secret';
$config->{'cookie.name'} ||= 'vroom';
$config->{'rooms.inactivity_timeout'} ||= 60;
$config->{'rooms.reserved_inactivity_timeout'} ||= 86400;
$config->{'rooms.common_names'} ||= '';

View File

@ -7,7 +7,7 @@ use base 'Exporter';
our @EXPORT = qw/DB_VERSION COMPONENTS MOH JS_STRINGS API_ACTIONS/;
# Database version
use constant DB_VERSION => 6;
use constant DB_VERSION => 7;
# Components used to generate the credits part
use constant COMPONENTS => {

View File

@ -145,3 +145,24 @@ if ($cur_ver < 6){
print "Successfully upgraded to schema version 6\n";
}
if ($cur_ver < 7){
print "Upgrading the schema to version 7\n";
eval {
$dbh->begin_work;
$dbh->do(qq{ CREATE TABLE `session_keys` (`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`key` VARCHAR(160) NOT NULL,
`date` DATETIME NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
INDEX (`date`))
ENGINE INNODB DEFAULT CHARSET=utf8; });
$dbh->do(qq{ UPDATE `config` SET `value`='7' WHERE `key`='schema_version' });
$dbh->commit;
};
if ($@){
print "An error occurred: " . $dbh->errstr . "\n";
local $dbh->{RaiseError} = 0;
$dbh->rollback;
exit 255;
};
print "Successfully upgraded to schema version 7\n";
}

View File

@ -358,17 +358,6 @@ cp /opt/vroom/conf/settings.ini.dist /opt/vroom/conf/settings.ini</pre>
</p>
<h3 id="settings_cookie">
cookie
</h3>
<p>
This section controls the cookie used for VROOM sessions. The available settings are
<ul>
<li><strong>secret</strong>: A secret passphrase to sign cookies. Must be changed !!!
<li><strong>name</strong>: The name of the cookie. Default is <strong>vroom</strong></li>
</ul>
</p>
<h3 id="settings_rooms">
rooms
</h3>

View File

@ -143,6 +143,39 @@ helper check_db_version => sub {
return ($ver eq Vroom::Constants::DB_VERSION) ? '1' : '0';
};
# Generate and manage rotation of session keys
# used to sign cookies
helper update_session_keys => sub {
my $self = shift;
# First, delete obsolete session keys
my $sth = eval {
$self->db->prepare('DELETE FROM `session_keys`
WHERE `date` < DATE_SUB(CONVERT_TZ(NOW(), @@session.time_zone, \'+00:00\'), INTERVAL 72 HOUR)');
};
$sth->execute;
# Now, retrieve all remaining keys, to check if we have enough of them
$sth = eval {
$self->db->prepare('SELECT `key` FROM `session_keys`
ORDER BY `date` DESC');
};
$sth->execute;
my $keys = $sth->fetchall_hashref('key');
my @keys = keys %$keys;
if (scalar @keys < 3){
$self->app->log->debug("Generating a new key to sign session cookies");
my $new_key = Session::Token->new(alphabet => ['a'..'z', 'A'..'Z', '0'..'9', '.:;,/!%$#~{([-_)]}=+*|'], entropy => 512)->get;
unshift @keys, $new_key;
$self->app->log->info("new key: $new_key");
$sth = eval {
$self->db->prepare('INSERT INTO `session_keys` (`key`,`date`)
VALUES (?,NOW())');
};
$sth->execute($new_key);
}
$self->app->secrets(\@keys);
return 1;
};
# Return human readable username if it exists, or just the session ID
helper get_name => sub {
my $self = shift;
@ -1231,6 +1264,11 @@ Mojo::IOLoop->recurring( 900 => sub {
app->purge_invitations;
});
# Check every 24h if session keys needs updating
Mojo::IOLoop->recurring( 86400 => sub {
app->update_session_keys;
});
# Route / to the index page
get '/' => sub {
my $self = shift;
@ -2070,10 +2108,12 @@ get '/:room' => sub {
# use the templates defined in the config
push @{app->renderer->paths}, 'templates/'.$config->{'interface.template'};
# Set the secret used to sign cookies
app->secrets([$config->{'cookie.secret'}]);
app->update_session_keys;
# Set log level
app->log->level($config->{'daemon.log_level'});
app->sessions->secure(1);
app->sessions->cookie_name($config->{'cookie.name'});
app->sessions->cookie_name('vroom');
app->hook(before_dispatch => sub {
my $self = shift;
# Switch to the desired language
@ -2109,8 +2149,6 @@ app->config(
}
);
# Set log level
app->log->level($config->{'daemon.log_level'});
app->log->info('Starting VROOM daemon');
# And start, lets VROOM !!
app->start;