Skip to content

Commit

Permalink
[backend] also cosign anonymous images in multiarch containers
Browse files Browse the repository at this point in the history
  • Loading branch information
mlschroe committed Jan 19, 2022
1 parent 4624669 commit 3da3168
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 17 deletions.
10 changes: 6 additions & 4 deletions src/backend/BSConSign.pm
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ use Digest::SHA ();
use MIME::Base64 ();
use IO::Compress::RawDeflate;

our $mt_cosign = 'application/vnd.dev.cosign.simplesigning.v1+json';

sub canonical_json {
return JSON::XS->new->utf8->canonical->encode($_[0]);
}
Expand Down Expand Up @@ -83,7 +85,7 @@ sub sig2openshift {
}

sub createcosign {
my ($signfunc, $digest, $reference, $creator, $timestamp) = @_;
my ($signfunc, $digest, $reference, $creator, $timestamp, $annotations) = @_;
my $payload = createpayload('cosign container image signature', $digest, $reference, $creator, $timestamp);
my $payload_digest = 'sha256:'.Digest::SHA::sha256_hex($payload);
# signfunc must return the openssl rsa signature
Expand All @@ -98,12 +100,12 @@ sub createcosign {
};
my $config_json = canonical_json($config);
my $payload_layer = {
'annotations' => { 'dev.cosignproject.cosign/signature' => $sig },
'annotations' => { 'dev.cosignproject.cosign/signature' => $sig, %{$annotations || {}} },
'digest' => $payload_digest,
'mediaType' => 'application/vnd.dev.cosign.simplesigning.v1+json',
'mediaType' => $mt_cosign,
'size' => length($payload),
};
return ($config_json, $payload_layer, $payload);
return ($config_json, $payload_layer, $payload, $sig);
}

1;
30 changes: 17 additions & 13 deletions src/backend/BSPublisher/Registry.pm
Original file line number Diff line number Diff line change
Expand Up @@ -141,14 +141,14 @@ sub push_blob {
return $blobid;
}

sub push_blob_string {
my ($repodir, $blobdata) = @_;
my $blob_id = 'sha256:'.Digest::SHA::sha256_hex($blobdata);
sub push_blob_content {
my ($repodir, $content) = @_;
my $blob_id = 'sha256:'.Digest::SHA::sha256_hex($content);
my $dir = "$repodir/:blobs";
return $blob_id if -e "$dir/$blob_id";
mkdir_p($dir) unless -d $dir;
unlink("$dir/.$blob_id.$$");
writestr("$dir/.$blob_id.$$", "$dir/$blob_id", $blobdata);
writestr("$dir/.$blob_id.$$", "$dir/$blob_id", $content);
return $blob_id;
}

Expand Down Expand Up @@ -432,7 +432,7 @@ sub update_sigs {
}

sub update_cosign {
my ($prp, $repo, $gun, $imagedigests, $pubkey, $signargs, $oci, $knownmanifests, $knownblobs) = @_;
my ($prp, $repo, $gun, $digests_to_cosign, $pubkey, $signargs, $knownmanifests, $knownblobs) = @_;

my $creator = 'OBS';
my ($projid, $repoid) = split('/', $prp, 2);
Expand All @@ -443,27 +443,28 @@ sub update_cosign {
my $signfunc = sub { BSUtil::xsystem($_[0], @signcmd, '-O', '-h', 'sha256') };
my $repodir = "$registrydir/$repo";
my $oldsigs = BSUtil::retrieve("$repodir/:cosign", 1) || {};
return if !%$oldsigs && !%$imagedigests;
return if !%$oldsigs && !%$digests_to_cosign;
my $gpgpubkey = BSPGP::unarmor($pubkey);
my $pubkey_fp = BSPGP::pk2fingerprint($gpgpubkey);
if (($oldsigs->{'pubkey'} || '') ne $pubkey_fp || ($oldsigs->{'gun'} || '') ne $gun || ($oldsigs->{'creator'} || '') ne ($creator || '')) {
$oldsigs = {}; # fingerprint/gun/creator mismatch, do not use old signatures
}
my $sigs = { 'pubkey' => $pubkey_fp, 'gun' => $gun, 'creator' => $creator, 'digests' => {} };
for my $digest (sort keys %$imagedigests) {
for my $digest (sort keys %$digests_to_cosign) {
my $oci = $digests_to_cosign->{$digest};
my $old = ($oldsigs->{'digests'} || {})->{$digest};
if ($old) {
$sigs->{'digests'}->{$digest} = $old;
next;
}
print "creating cosign signature for $gun $digest\n";
my ($config, $payload_layer, $payload) = BSConSign::createcosign($signfunc, $digest, $gun, $creator);
my $config_blobid = push_blob_string($repodir, $config);
my $config_blobid = push_blob_content($repodir, $config);
$knownblobs->{$config_blobid} = 1;
my $payload_blobid = push_blob_string($repodir, $payload);
my $payload_blobid = push_blob_content($repodir, $payload);
$knownblobs->{$payload_blobid} = 1;
die unless $payload_blobid eq $payload_layer->{'digest'};
my $config_data = {
my $config_data = {
'mediaType' => $oci ? $BSContar::mt_oci_config : $BSContar::mt_docker_config,
'size' => length($config),
'digest' => $config_blobid,
Expand Down Expand Up @@ -511,6 +512,7 @@ sub push_containers {
my %knownmanifests;
my %knowntags;
my %knownimagedigests;
my %digests_to_cosign;

my %info;

Expand Down Expand Up @@ -627,6 +629,7 @@ sub push_containers {
my $mani_json = BSContar::create_dist_manifest($mani);
my $mani_id = push_manifest($repodir, $mani_json);
$knownmanifests{$mani_id} = 1;
$digests_to_cosign{$mani_id} = $oci;

my $multimani = {
'mediaType' => $mediaType,
Expand Down Expand Up @@ -680,6 +683,7 @@ sub push_containers {
$mani_size = length($mani_json);
$knownmanifests{$mani_id} = 1;
$taginfo->{'distmanifesttype'} = 'list';
$digests_to_cosign{$mani_id} = $oci;
} else {
$mani_id = $multimanifests[0]->{'digest'};
$mani_size = $multimanifests[0]->{'size'};
Expand All @@ -692,9 +696,9 @@ sub push_containers {
$info{$tag} = $taginfo;
}

# write signatures file
if ($gun && %knownimagedigests) {
update_cosign($prp, $repo, $gun, \%knownimagedigests, $pubkey, $signargs, 0, \%knownmanifests, \%knownblobs);
# write signatures file (need to do this early as it adds manifests/blobs)
if ($gun && %digests_to_cosign) {
update_cosign($prp, $repo, $gun, \%digests_to_cosign, $pubkey, $signargs, \%knownmanifests, \%knownblobs);
} elsif (-e "$repodir/:cosign") {
unlink("$repodir/:cosign");
}
Expand Down

0 comments on commit 3da3168

Please sign in to comment.