Skip to content

Commit

Permalink
[backend] implement provenance file generation for container builds
Browse files Browse the repository at this point in the history
Add the rpms of the build environment and the rpms that were used
when building the container to the provenance file.
  • Loading branch information
mlschroe committed Oct 4, 2022
1 parent 5ddcdb5 commit e056f2b
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 9 deletions.
13 changes: 13 additions & 0 deletions src/backend/BSRepServer/Containertar.pm
Expand Up @@ -147,6 +147,7 @@ sub stat_container {
$s[7] = $containerinfo->{'tar_size'};
$s[9] = $containerinfo->{'tar_mtime'};
$s[20] = $containerinfo->{'tar_md5sum'};
$s[21] = $containerinfo->{'tar_sha256sum'};
return @s;
}

Expand All @@ -167,6 +168,18 @@ sub open_container {
return $fd;
}

sub write_container {
my ($container, $fn, $fnf, $sha256sum) = @_;
my $containerinfo = get_containerinfo($container);
return undef unless $containerinfo;
return undef if $sha256sum && $containerinfo->{'tar_sha256sum'} ne $sha256sum;
my $dir = $container;
$dir =~ s/[^\/]*$/./;
my ($tar, undef, $mtime) = construct_container_tar($dir, $containerinfo, 1);
BSTar::writetarfile($fn, $fnf, $tar, 'mtime' => $mtime);
return 1;
}

sub add_containers {
my %tars;
for (sort @_) {
Expand Down
24 changes: 19 additions & 5 deletions src/backend/BSRepServer/SLSA.pm
Expand Up @@ -18,13 +18,15 @@ package BSRepServer::SLSA;

use strict;

use Digest::SHA ();
use Data::Dumper;
use DBI qw(:sql_types);

use BSConfiguration;
use BSUtil;
use BSSQLite;
use Digest::SHA ();
use Data::Dumper;
use BSRepServer::Containertar;

use DBI qw(:sql_types);

my $reporoot = "$BSConfig::bsdir/build";
my $slsadir = "$BSConfig::bsdir/slsa";
Expand Down Expand Up @@ -91,7 +93,13 @@ sub link_binary {
my $ent = $gbininfo->{$packid}->{$k};
next unless $ent->{'name'} && ($ent->{'name'} eq $binname1 || $ent->{'name'} eq $binname2);
unlink($tmp);
next unless link("$reporoot/$prpa/$packid/$ent->{'filename'}", $tmp);
if ($ent->{'filename'} =~ /\.obsbinlnk$/ && $hint =~ /\.tar$/) {
my $fn = "$reporoot/$prpa/$packid/$ent->{'filename'}";
$fn =~ s/\.obsbinlnk/\.tar/;
next unless BSRepServer::Containertar::write_container($fn, $tmp, $digest);
} else {
next unless link("$reporoot/$prpa/$packid/$ent->{'filename'}", $tmp);
}
unlink("$tmp.prov");
link("$reporoot/$prpa/$packid/_slsa_provenance.json", "$tmp.prov");
return 1 if sha256file($tmp) eq $digest;
Expand All @@ -117,7 +125,13 @@ sub link_binary_from_full {
for my $bin (sort(ls("$reporoot/$prpa/:full"))) {
if (($binname1 && $bin =~ /^\Q$binname1\E[-_\.]/) || ($binname2 && $bin =~ /^\Q$binname2\E[-_\.]/)) {
unlink($tmp);
next unless link("$reporoot/$prpa/:full/$bin", $tmp);
if ($bin =~ /\.obsbinlnk$/ && $hint =~ /\.tar$/) {
my $fn = "$reporoot/$prpa/:full/$bin";
$fn =~ s/\.obsbinlnk/\.tar/;
next unless BSRepServer::Containertar::write_container($fn, $tmp, undef, $digest);
} else {
next unless link("$reporoot/$prpa/:full/$bin", $tmp);
}
unlink("$tmp.prov");
return 1 if sha256file($tmp) eq $digest;
}
Expand Down
36 changes: 32 additions & 4 deletions src/backend/bs_worker
Expand Up @@ -2497,6 +2497,7 @@ sub getbinaries_containers {
$res = [ grep {$_->{'name'} ne '.errors'} @$res ];
die("getbinaries: missing packages: $bdep->{'name'}\n") unless @$res == 1;
my $tarname = $res->[0]->{'name'};
add_slsa_materials_binary($buildinfo, "$repo->{'project'}/$repo->{'repository'}/$buildinfo->{'arch'}", $tarname, "$ddir/$tarname", 'containers') if $buildinfo->{'slsaprovenance'};
my $kiwimode = getkiwimode($buildinfo);
if ($kiwimode eq 'image' && $tarname =~ /\.tar$/) {
system('gzip', '-f', '-1', "$ddir/$tarname") && die("kiwi container compression: $?\n");
Expand Down Expand Up @@ -2557,6 +2558,12 @@ sub getbinaries_kiwiimage {
last unless @todo;
my $server = $repo->{'server'} || $buildinfo->{'reposerver'};
my $got = getbinaries_cache($dir, $server, $repo->{'project'}, $repo->{'repository'}, $syspatharch, 1, \@todo, $modules);
if ($buildinfo->{'slsaprovenance'}) {
for my $n (sort keys %$got) {
my $f = $got->{$n};
add_slsa_materials_binary($buildinfo, "$repo->{'project'}/$repo->{'repository'}/$syspatharch", $f->{'name'}, "$dir/$f->{'name'}");
}
}
@todo = grep {!$got->{$_}} @todo;
}
die("getbinaries: missing packages: @todo\n") if @todo;
Expand Down Expand Up @@ -2601,6 +2608,7 @@ sub getbinaries_kiwiimage {
if (!$buildinfo->{'syspath'} && !$bdep_noinstall{$n}) {
if (!-e "$dir/$f->{'name'}") {
link_or_copy("$ddir/$f->{'name'}", "$dir/$f->{'name'}") || die("link_or_copy $ddir/$f->{'name'} $dir/$f->{'name'}: $!\n");
add_slsa_materials_binary($buildinfo, "$repo->{'project'}/$repo->{'repository'}/$arch", $f->{'name'}, "$dir/$f->{'name'}") if $buildinfo->{'slsaprovenance'};
}
unlink("$ddir/$f->{'name'}") if $bdep_notmeta{$n};
}
Expand Down Expand Up @@ -3151,6 +3159,18 @@ sub createreport {
local *F;
for my $file (grep {/\.packages$/} sort(ls($dir))) {
next unless open(F, '<', "$dir/$file");
# get basepackages if available
my $bfile = $file;
$bfile =~ s/\.packages$/.basepackages/;
my %baseentries;
my $bf;
if (open($bf, '<', "$dir/$bfile")) {
while(<$bf>) {
chomp;
$baseentries{$_} = 1;
}
close($bf);
}
my @bins;
while (<F>) {
chomp;
Expand Down Expand Up @@ -3179,8 +3199,14 @@ sub createreport {
}
}
my $prpap = $kiwiorigins->{$s[0]};
if ($prpap) {
if ($prpap && !$baseentries{$_}) {
my ($projid, $repoid, $arch, $packid) = split('/', $prpap, 4);
if ($buildinfo->{'slsaprovenance'}) {
my $fn;
$fn = "$s[0].rpm" if -e "$srcdir/repos/$projid/$repoid/$s[0].rpm";
$fn = "$s[0].deb" if -e "$srcdir/repos/$projid/$repoid/$s[0].deb";
add_slsa_materials_binary($buildinfo, "$projid/$repoid/$arch", $fn, "$srcdir/repos/$projid/$repoid/$fn", 'repos') if $fn;
}
$bin->{'project'} = $projid;
$bin->{'repository'} = $repoid;
$bin->{'arch'} = $arch;
Expand Down Expand Up @@ -3252,7 +3278,7 @@ my $slsa_json_template = {
'reproducible' => 'bool',
},
'materials' => {
'_order' => ['uri', 'digest' ],
'_order' => ['uri', 'digest', 'intent' ],
}
}
};
Expand Down Expand Up @@ -3333,7 +3359,7 @@ sub add_slsa_materials_sourcefile {
}

sub add_slsa_materials_binary {
my ($buildinfo, $prpa, $filename, $localfile) = @_;
my ($buildinfo, $prpa, $filename, $localfile, $intent) = @_;
my $sha256sum = sha256file($localfile);
my $uri;
if ($buildinfo->{'slsadownloadurl'} && $buildinfo->{'slsadownloadurl'} =~ /\/_slsa$/) {
Expand All @@ -3345,7 +3371,9 @@ sub add_slsa_materials_binary {
my $server = $buildinfo->{'slsadownloadurl'} || $buildinfo->{'srcserver'} || $srcserver;
$uri = BSHTTP::urlencode("$server/slsa/$prpa/$filename/$sha256sum");
}
push @{$buildinfo->{'materials'}}, { 'uri' => $uri, 'digest' => { 'sha256' => $sha256sum } };
my $m = { 'uri' => $uri, 'digest' => { 'sha256' => $sha256sum } };
$m->{'intent'} = $intent if $intent;
push @{$buildinfo->{'materials'}}, $m;
}

sub add_slsa_materials_config {
Expand Down

0 comments on commit e056f2b

Please sign in to comment.