[#3] Added own SSL certificate support.
authorStanislaw Klekot <dozzie@jarowit.net>
Wed, 31 Aug 2011 11:51:03 +0000 (13:51 +0200)
committerStanislaw Klekot <dozzie@jarowit.net>
Fri, 2 Sep 2011 14:15:10 +0000 (16:15 +0200)
cronbuilder
lib/Cron/Builder/Repo.pm
lib/Cron/Builder/Repo/git.pm
lib/Cron/Builder/Repo/svn.pm
sample-env/cronbuilder.yaml

index d9cf00d..be6f167 100755 (executable)
@@ -12,6 +12,7 @@ use Cwd qw{realpath getcwd};
 use Getopt::Long;
 use Fcntl qw{:flock};
 use POSIX qw{O_WRONLY O_CREAT};
+use File::Copy qw{copy};
 
 #-----------------------------------------------------------------------------
 
@@ -54,6 +55,37 @@ sub run_unlock {
 
 #-----------------------------------------------------------------------------
 
+sub copy_if_different {
+  my ($src, $dst) = @_;
+
+  if (not -e $dst) {
+    copy($src, $dst);
+    return;
+  }
+
+  my $bs;
+  my $bd;
+
+  open my $fs, "<", $src or die "Can't open file $src: $!";
+  open my $fd, "<", $dst;
+  while (sysread($fs, $bs, 1024) > 0 && sysread($fd, $bd, 1024) > 0) {
+    # XXX: assume the reads finished successfully
+    if ($bs ne $bd) {
+      close $fs;
+      close $fd;
+      copy($src, $dst);
+      return;
+    }
+  }
+
+  # no operation needed (files are the same)
+  close $fs;
+  close $fd;
+  return;
+}
+
+#-----------------------------------------------------------------------------
+
 sub usage {
   printf "Usage:\n" .
          "  %s [options] working-directory\n\n",
@@ -140,6 +172,22 @@ $config{build}{rebuild} = "true" if $opts{rebuild};
 #-----------------------------------------------------------------------------
 # update repositories
 
+# first, prepare possible SSL stuff
+if (defined $config{source}{ssl_ca}) {
+  mkdir "ssl" if not -d "ssl";
+  # I would use .cert.pem suffix, but I don't know if it is a PEM or DER or
+  # anything else
+  copy_if_different($config{source}{ssl_ca}, "ssl/source.crt");
+  $config{source}{ssl_ca} = "ssl/source.crt";
+}
+if (defined $config{destination}{ssl_ca}) {
+  mkdir "ssl" if not -d "ssl";
+  # I would use .cert.pem suffix, but I don't know if it is a PEM or DER or
+  # anything else
+  copy_if_different($config{destination}{ssl_ca}, "ssl/dest.crt");
+  $config{destination}{ssl_ca} = "ssl/dest.crt";
+}
+
 my $src = new Cron::Builder::Repo(
   %{ $config{source} },
   prefix   => $config{build}{prefix},
index 2c01ea2..ce5e9f3 100644 (file)
@@ -72,6 +72,11 @@ credentials.
 
 Prefix to look for in C<build_revision()>.
 
+=item C<ssl_ca>
+
+Path to X.509 certificate authority (or a server self-signed certificate) that
+will be used to protect transmission with SSL.
+
 =back
 
 For exact list of options, see engines' documentation.
index 6fa95c6..2202bfe 100644 (file)
@@ -21,6 +21,7 @@ use Cwd qw{getcwd realpath};
 use Cron::Builder qw{spawn};
 use File::Path qw{rmtree};
 use File::Find;
+use File::Spec;
 
 #-----------------------------------------------------------------------------
 
@@ -64,6 +65,15 @@ F<./git-config> will be used.
 If repository C<url> requires authentication, this is the place to provide the
 credentials.
 
+=item C<prefix>
+
+Prefix to look for in C<build_revision()>. See L<Cron::Builder::Repo>.
+
+=item C<ssl_ca>
+
+Path to X.509 certificate authority (or a server self-signed certificate) that
+will be used to protect transmission with SSL.
+
 =back
 
 =cut
@@ -132,9 +142,23 @@ sub checkout {
     printf $netrc "password %s\n", $self->{password};
     close $netrc;
 
+    if (defined $self->{ssl_ca}) {
+      my $relpath = File::Spec->abs2rel($self->{ssl_ca}, $self->{workdir});
+
+      open my $gitconfig, ">", "$self->{statedir}/.gitconfig"
+        or die "Can't write to $self->{statedir}/.gitconfig: $!";
+      printf $gitconfig "[http]\n\tsslCAInfo = %s\n", $relpath;
+      close $gitconfig;
+    }
+
     umask $umask;
   }
 
+  # when cloning, we're not yet in working copy, so the path relative to
+  # working copy is invalid and needs to be overriden by path passed in
+  # constructor
+  local $ENV{GIT_SSL_CAINFO} = $self->{ssl_ca};
+
   local $ENV{HOME} = $self->{statedir};
   my $log = spawn("git", "clone", $self->{url}, $self->{workdir});
   if ($? == 0 && $log =~ /^warning: remote HEAD refers to nonexistent ref/m) {
index a5da7a3..26d2fd2 100644 (file)
@@ -64,6 +64,15 @@ F<./svn-config> will be used.
 If repository C<url> requires authentication, this is the place to provide the
 credentials.
 
+=item C<prefix>
+
+Prefix to look for in C<build_revision()>. See L<Cron::Builder::Repo>.
+
+=item C<ssl_ca>
+
+Path to X.509 certificate authority (or a server self-signed certificate) that
+will be used to protect transmission with SSL.
+
 =back
 
 =cut
@@ -81,6 +90,9 @@ sub new {
     open my $f, ">", "$self->{statedir}/servers" or
       die "Can't prepare SVN configuration";
     printf $f "[global]\nstore-plaintext-passwords = yes\n";
+    if (defined $self->{ssl_ca}) {
+      printf $f "ssl-authority-files = %s\n", $self->{ssl_ca};
+    }
     close $f;
   }
 
index 5708d42..5371849 100644 (file)
@@ -8,6 +8,7 @@ source:
   #url: "file:///var/lib/subversion"
   #user: xx
   #password: yy
+  #ssl_ca: path/to/x.509.cert.pem
 
 destination:
   # type: svn, git
@@ -19,6 +20,7 @@ destination:
   #url: "https://.../..."
   #user: xx
   #password: yy
+  #ssl_ca: path/to/x.509.cert.pem
 
 build:
   # specify how to produce destination data from source data