mark: A photo of Mark kneeling on top of the Taal Volcano in the Philippines. It was a long hike. (Default)
Mark Smith ([staff profile] mark) wrote in [site community profile] changelog2012-04-29 07:11 am

[dw-free] Tools to manage %LJ::SECRETS

[commit: http://hg.dwscoalition.org/dw-free/rev/dd765fec7dac]

http://bugs.dwscoalition.org/show_bug.cgi?id=4084

Add secret generating/documentation framework

Patch by [personal profile] exor674.

Files modified:
  • bin/checkconfig.pl
  • bin/upgrading/gen-secrets.pl
  • cgi-bin/LJ/Global/Defaults.pm
  • cgi-bin/LJ/Global/Secrets.pm
  • cgi-bin/ljlib.pl
--------------------------------------------------------------------------------
diff -r acb4c85567e3 -r dd765fec7dac bin/checkconfig.pl
--- a/bin/checkconfig.pl	Sun Apr 29 00:18:57 2012 +0000
+++ b/bin/checkconfig.pl	Sun Apr 29 07:12:05 2012 +0000
@@ -27,6 +27,7 @@
     "modules",
     "env",
     "database",
+    "secrets",
 );
 foreach my $check (@checks) { $dochecks{$check} = 1; }
 
@@ -51,6 +52,7 @@
 if ($debs_only) {
     $dochecks{database} = 0;
     $dochecks{timezone} = 0;
+    $dochecks{secrets} = 0;
 }
 
 usage() if $only_check && $no_check;
@@ -379,3 +381,40 @@
     $err->( "Timezone must be UTC." ) unless $timezone->is_utc;
 }
 
+sub check_secrets {
+    print "[Checking Secrets...]\n";
+
+    foreach my $secret ( keys %LJ::Secrets::secret ) {
+        my $def = $LJ::Secrets::secret{$secret};
+        my $req_len = exists $def->{len} || exists $def->{min_len} || exists $def->{max_len};
+        my $rec_len = exists $def->{rec_len} || exists $def->{rec_min_len} || exists $def->{rec_max_len};
+
+        my $req_min = $def->{len} || $def->{min_len} || 0;
+        my $req_max = $def->{len} || $def->{max_len} || 0;
+
+        my $rec_min = $def->{rec_len} || $def->{rec_min_len} || 0;
+        my $rec_max = $def->{rec_len} || $def->{rec_max_len} || 0;
+        my $val = $LJ::SECRETS{$secret} || '';
+        my $len = length( $val );
+
+        if ( ! defined( $LJ::SECRETS{$secret} ) || ! $LJ::SECRETS{$secret} ) {
+            if ( $def->{required} ) {
+                $err->( "Missing requred secret '$secret': $def->{desc}" );
+            } else {
+                print STDERR "Missing optional secret '$secret': $def->{desc}\n";
+            }
+        } elsif ( $req_len && ( $len < $req_min || $len > $req_max ) ) {
+            if ( $req_min == $req_max ) {
+                $err->( "Secret '$secret' not of required length: is $len, must be $req_min" );
+            } else {
+                $err->( "Secret '$secret' not of required length: is $len, must be between $req_min and $req_max" );
+            }
+        } elsif ( $rec_len && ( $len < $rec_min || $len > $rec_max ) ) {
+            if ( $rec_min == $rec_max ) {
+                print STDERR "Secret '$secret' not of recommended length: is $len, should be $rec_min\n";
+            } else {
+                print STDERR "Secret '$secret' not of recommended length: is $len, should be between $rec_min and $rec_max\n";
+            }
+        }
+    }
+}
diff -r acb4c85567e3 -r dd765fec7dac bin/upgrading/gen-secrets.pl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/upgrading/gen-secrets.pl	Sun Apr 29 07:12:05 2012 +0000
@@ -0,0 +1,107 @@
+#!/usr/bin/perl
+#
+# bin/upgrading/gen-secrets.pl
+#
+# This script can generate items for %LJ::SECRETS
+#
+# Authors:
+#      Andrea Nall <anall@andreanall.com>
+#
+# Copyright (c) 2011 by Dreamwidth Studios, LLC.
+#
+# This program is free software; you may redistribute it and/or modify it under
+# the same terms as Perl itself.  For a copy of the license, please reference
+# 'perldoc perlartistic' or 'perldoc perlgpl'.
+#
+use strict;
+use lib "$ENV{LJHOME}/cgi-bin";
+use Getopt::Long;
+use POSIX;
+use Data::Dumper;
+
+BEGIN { require "ljlib.pl"; }
+
+my $tv = system('openssl version >/dev/null 2>/dev/null');
+die "OpenSSL command line not found" if $tv;
+
+sub usage {
+    die "Usage: gen-secrets.pl BLAH";
+}
+
+my $regen = 0;
+my $no_rec= 0;
+
+usage() unless GetOptions(
+                          'regen'       => \$regen,
+                          'required'    => \$no_rec,
+                          );
+
+my %sec_use;
+%sec_use = %LJ::SECRETS unless $regen;
+
+my %sec_out;
+
+foreach my $secret ( sort keys %LJ::Secrets::secret ) {
+    my $def = $LJ::Secrets::secret{$secret};
+
+    next if defined $sec_use{$secret} && $sec_use{$secret};
+    next if $no_rec && ! $def->{required};
+
+    if ( $def->{max_len} && $def->{min_len} && $def->{max_len} < $def->{min_len} ) {
+        warn "Invalid required length specifications ( max < min ) for '$secret'.\n";
+        next;
+    }
+
+    if ( $def->{rec_max_len} && $def->{rec_min_len} && $def->{rec_max_len} < $def->{rec_min_len} ) {
+        warn "Invalid recommended length specifications ( max < min ) for '$secret'.\n";
+        next;
+    }
+
+    my $req_len = $def->{len} || $def->{max_len} || $def->{min_len};
+    my $len = $req_len || $def->{rec_len} || $def->{rec_max_len} || $def->{rec_min_len};
+
+    if ( $len < 0 ) {
+        warn "Length for '$secret' is less then 0";
+        next;
+    }
+
+    my $gen_len = ceil( $len / 2 );
+    my $data = substr( `openssl rand -hex $gen_len`, 0, $len );
+    chomp $data;
+    die "Unable to get $len bytes of data from OpenSSL\n"
+        if length($data) < $len;
+
+    $sec_out{$secret} = $data;
+}
+
+unless ( %sec_out ) {
+    print "Your secrets are up to date.\n";
+    exit;
+}
+
+if ( ! %LJ::SECRETS ) {
+    print "\nPlease add the following section to your etc/config-private.pl file,\n";
+    print "inside the LJ package:\n\n";
+    print "%LJ::SECRETS = (\n";
+} else {
+    print "\nPlease add or replace the following sections in LJ::SECRETS in your config\n";
+    print "file (probably etc/config-private.pl):\n\n";
+}
+
+foreach my $secret ( sort keys %sec_out ) {
+    my $value = $sec_out{$secret};
+    # FIXME: There has to be a better way to do this.
+    $value =~ s/\\/\\\\/g;
+    $value =~ s/'/\\'/g;
+
+    if ( $secret =~ m/^[a-zA-Z0-9_]+$/ ) {
+        print "    $secret => '$value',\n";
+    } else {
+        $secret =~ s/\\/\\\\/g;
+        $secret =~ s/'/\\'/g;
+        print "    '$secret' => '$value',\n";
+    }
+}
+
+print ");\n" unless %LJ::SECRETS;
+print "\n";
diff -r acb4c85567e3 -r dd765fec7dac cgi-bin/LJ/Global/Defaults.pm
--- a/cgi-bin/LJ/Global/Defaults.pm	Sun Apr 29 00:18:57 2012 +0000
+++ b/cgi-bin/LJ/Global/Defaults.pm	Sun Apr 29 07:12:05 2012 +0000
@@ -369,6 +369,8 @@
     # default location of community posting guidelines
     $DEFAULT_POSTING_GUIDELINES_LOC ||= "N";
 
+    # Secrets
+    %SECRETS = () unless defined %SECRETS;
 }
 
 
diff -r acb4c85567e3 -r dd765fec7dac cgi-bin/LJ/Global/Secrets.pm
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cgi-bin/LJ/Global/Secrets.pm	Sun Apr 29 07:12:05 2012 +0000
@@ -0,0 +1,37 @@
+#!/usr/bin/perl
+#
+# LJ::Global::Secrets
+#
+# This module provides a list of definitions for
+# items in %LJ::SECRETS
+#
+# Authors:
+#      Andrea Nall <anall@andreanall.com>
+#
+# Copyright (c) 2011 by Dreamwidth Studios, LLC.
+#
+# This program is free software; you may redistribute it and/or modify it under
+# the same terms as Perl itself.  For a copy of the license, please reference
+# 'perldoc perlartistic' or 'perldoc perlgpl'.
+#
+
+use strict;
+package LJ::Secrets;
+our %secret;
+
+# Potential flags
+#   desc -- english description, only showed in internal tools
+#   required -- requred for basic site operation, v.s. additional features
+#
+#   rec_len -- recommended length, implies rec_min_len/rec_max_len
+#   rec_min_len -- recommended minumum length
+#   rec_max_len -- recommended maximum length
+#
+#   len -- required len, implies min_len/max_len
+#   min_len -- required minimim length
+#   max_len -- required maximum length
+
+$secret{invite_img_auth} = {
+    desc => "Auth code for invite code status images",
+    rec_len => 64,
+};
diff -r acb4c85567e3 -r dd765fec7dac cgi-bin/ljlib.pl
--- a/cgi-bin/ljlib.pl	Sun Apr 29 00:18:57 2012 +0000
+++ b/cgi-bin/ljlib.pl	Sun Apr 29 07:12:05 2012 +0000
@@ -108,6 +108,7 @@
 use LJ::Capabilities;
 use DW::Mood;
 use LJ::Global::Img;  # defines LJ::Img
+use LJ::Global::Secrets;  # defines LJ::Secrets
 
 require "$LJ::HOME/cgi-bin/ljlib-local.pl"
     if -e "$LJ::HOME/cgi-bin/ljlib-local.pl";
--------------------------------------------------------------------------------