Introduce autorotating secrets for security
Change-Id: I25a4c44841e13ee1d151c87cdaaeedc5ab704765
diff --git a/.gitignore b/.gitignore
index 90ca657..84cb25a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,5 @@
/cache
-/kalamar.secret
+/kalamar.secret*
/start-test
/todo.org
/fixtures.txt
diff --git a/Changes b/Changes
index 85fa8b5..e348e74 100755
--- a/Changes
+++ b/Changes
@@ -18,9 +18,16 @@
- List tokens of a client.
- Upgrade Mojolicious dependency to 9.19.
- Added query reference API.
+ - Use AutoSecrets plugin to improve security.
WARNING: Upgrading to Mojolicious 9.19 will
invalidate all sessions. This is a security update.
+
+ WARNING: Even testing this distribution will rewrite your
+ kalamar.secret file to migrate to kalamar.secret.json.
+ It will keep kalamar.secret - but you'll advise to
+ delete the file after checking the integrity with
+ kalamar.secret.json.
0.41 2021-03-01
- Introduce CORS headers to the proxy.
diff --git a/Makefile.PL b/Makefile.PL
index 40de23c..2ed9908 100644
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -25,6 +25,7 @@
'Mojolicious::Plugin::Util::RandomString' => 0.09,
'Mojolicious::Plugin::CHI' => 0.20,
'Mojolicious::Plugin::ClientIP' => 0.02,
+ 'Mojolicious::Plugin::AutoSecrets' => 0.006,
'Cache::FastMmap' => 1.56,
'Data::Serializer' => 0.65,
'Mojo::JWT' => 0.09,
diff --git a/README.md b/README.md
index 04ff442..5cfa713 100644
--- a/README.md
+++ b/README.md
@@ -153,9 +153,10 @@
### Secret file
-Kalamar uses [rotating secrets](https://mojolicious.org/perldoc/Mojolicious#secrets)
-to sign cookies. Put a file called `kalamar.secret` in the root of the application
-with one secret per line.
+Kalamar uses auto rotating secrets. Allow access to a file called
+`kalamar.secret.json` in the home directory of kalamar. It will
+automatically be created, if it doesn't exist.
+(`kalamar.secret` is deprecated.)
### Localization
diff --git a/lib/Kalamar.pm b/lib/Kalamar.pm
index a4893ad..4f619a6 100644
--- a/lib/Kalamar.pm
+++ b/lib/Kalamar.pm
@@ -3,12 +3,12 @@
use Mojo::ByteStream 'b';
use Mojo::URL;
use Mojo::File;
-use Mojo::JSON 'decode_json';
+use Mojo::JSON qw/decode_json encode_json/;
use Mojo::Util qw/url_escape deprecated slugify/;
use List::Util 'none';
# Minor version - may be patched from package.json
-our $VERSION = '0.41';
+our $VERSION = '0.42';
# Supported version of Backend API
our $API_VERSION = '1.0';
@@ -38,19 +38,41 @@
push(@{$self->plugins->namespaces}, __PACKAGE__ . '::Plugin');
# Set secrets for signed cookies
- if (-e (my $secret = $self->home->child('kalamar.secret'))) {
+ my $secret_file = $self->home->rel_file('kalamar.secret.json');
+
+ # Support old secrets file
+ # This is deprecated 2021-03-05
+ if (-e (my $old_secret = $self->home->child('kalamar.secret'))) {
# Load file and split lines for multiple secrets
- $self->secrets([b($secret->slurp)->split("\n")]);
+ my $secrets = [b($old_secret->slurp)->split("\n")];
+ $self->secrets($secrets);
+
+ eval {
+ $secret_file->spurt(encode_json(@$secrets));
+ $secret_file->chmod(0600);
+ if (-w $secret_file) {
+ $self->log->warn(
+ "Please delete $old_secret file " .
+ "- $secret_file was created instead"
+ );
+ }
+ };
+ if ($@) {
+ $self->log->error("Please make $secret_file accessible");
+ };
}
# File not found ...
# Kalamar needs secrets in a file to be easily deployable
# and publishable at the same time.
else {
- $self->log->warn('Please create a kalamar.secret file');
+ $self->plugin(AutoSecrets => {
+ path => $secret_file
+ });
};
+
# Configuration framework
$self->plugin('Config');
diff --git a/t/base.t b/t/base.t
new file mode 100644
index 0000000..f7f2e53
--- /dev/null
+++ b/t/base.t
@@ -0,0 +1,17 @@
+use Mojo::Base -strict;
+use Test::More;
+use Test::Mojo;
+use Mojo::JSON qw'decode_json';
+
+my $t = Test::Mojo->new('Kalamar');
+
+ok(my $file = $t->app->home->rel_file('kalamar.secret.json'));
+ok(-e $file, 'File exists');
+
+my $secrets = decode_json($file->slurp);
+ok(@$secrets >= 1);
+ok(length $secrets->[0] >= 5);
+
+ok($file->lstat->mode & 0600);
+
+done_testing;